diff --git a/CHANGELOG.md b/CHANGELOG.md index 72ca668717..d63f2ce356 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -159,6 +159,131 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun - **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) - **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. diff --git a/changelog.d/features/6818-antigravity-weekly-quota.md b/changelog.d/features/6818-antigravity-weekly-quota.md deleted file mode 100644 index 84abe02d9d..0000000000 --- a/changelog.d/features/6818-antigravity-weekly-quota.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). diff --git a/changelog.d/features/6820-codex-effort-model-echo.md b/changelog.d/features/6820-codex-effort-model-echo.md deleted file mode 100644 index d9646f81a3..0000000000 --- a/changelog.d/features/6820-codex-effort-model-echo.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. diff --git a/changelog.d/features/6823-zai-web-cookie-provider.md b/changelog.d/features/6823-zai-web-cookie-provider.md deleted file mode 100644 index 57100fc05c..0000000000 --- a/changelog.d/features/6823-zai-web-cookie-provider.md +++ /dev/null @@ -1 +0,0 @@ -- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) diff --git a/changelog.d/features/6836-import-providers-from-file.md b/changelog.d/features/6836-import-providers-from-file.md deleted file mode 100644 index fadbee0c6d..0000000000 --- a/changelog.d/features/6836-import-providers-from-file.md +++ /dev/null @@ -1 +0,0 @@ -- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) diff --git a/changelog.d/features/6838-headroom-gcf-v3.2-nested-flattening.md b/changelog.d/features/6838-headroom-gcf-v3.2-nested-flattening.md deleted file mode 100644 index 5752b80a24..0000000000 --- a/changelog.d/features/6838-headroom-gcf-v3.2-nested-flattening.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). diff --git a/changelog.d/features/6842-openrouter-quota-tracking.md b/changelog.d/features/6842-openrouter-quota-tracking.md deleted file mode 100644 index 5cd075a818..0000000000 --- a/changelog.d/features/6842-openrouter-quota-tracking.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). diff --git a/changelog.d/features/6844-grok-cli-quota.md b/changelog.d/features/6844-grok-cli-quota.md deleted file mode 100644 index fa80a10fc3..0000000000 --- a/changelog.d/features/6844-grok-cli-quota.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). diff --git a/changelog.d/features/6845-v0-vercel-quota-tracking.md b/changelog.d/features/6845-v0-vercel-quota-tracking.md deleted file mode 100644 index 0850845b78..0000000000 --- a/changelog.d/features/6845-v0-vercel-quota-tracking.md +++ /dev/null @@ -1 +0,0 @@ -- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). diff --git a/changelog.d/features/6846-nvidia-nim-quota.md b/changelog.d/features/6846-nvidia-nim-quota.md deleted file mode 100644 index df3897244e..0000000000 --- a/changelog.d/features/6846-nvidia-nim-quota.md +++ /dev/null @@ -1 +0,0 @@ -- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). diff --git a/changelog.d/features/6850-agentrouter-quota-tracking.md b/changelog.d/features/6850-agentrouter-quota-tracking.md deleted file mode 100644 index 8f8f700b3c..0000000000 --- a/changelog.d/features/6850-agentrouter-quota-tracking.md +++ /dev/null @@ -1 +0,0 @@ -- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). diff --git a/changelog.d/features/6862-gpt-5-6-providers.md b/changelog.d/features/6862-gpt-5-6-providers.md deleted file mode 100644 index 695473c505..0000000000 --- a/changelog.d/features/6862-gpt-5-6-providers.md +++ /dev/null @@ -1,2 +0,0 @@ -- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun -- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun diff --git a/changelog.d/features/6872-relay-routing-fallback-reason-header.md b/changelog.d/features/6872-relay-routing-fallback-reason-header.md deleted file mode 100644 index 85856e2245..0000000000 --- a/changelog.d/features/6872-relay-routing-fallback-reason-header.md +++ /dev/null @@ -1 +0,0 @@ -- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) diff --git a/changelog.d/features/6873-model-latency-stats-api.md b/changelog.d/features/6873-model-latency-stats-api.md deleted file mode 100644 index 1b5b0656e5..0000000000 --- a/changelog.d/features/6873-model-latency-stats-api.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). diff --git a/changelog.d/features/6874-vibeproxy-openai-provider-node-preset.md b/changelog.d/features/6874-vibeproxy-openai-provider-node-preset.md deleted file mode 100644 index 8a55e40627..0000000000 --- a/changelog.d/features/6874-vibeproxy-openai-provider-node-preset.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) diff --git a/changelog.d/features/6875-latency-stats-ttft.md b/changelog.d/features/6875-latency-stats-ttft.md deleted file mode 100644 index 22d8028d8d..0000000000 --- a/changelog.d/features/6875-latency-stats-ttft.md +++ /dev/null @@ -1 +0,0 @@ -- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) diff --git a/changelog.d/features/6879-default-reasoning-effort.md b/changelog.d/features/6879-default-reasoning-effort.md deleted file mode 100644 index ff62a749d6..0000000000 --- a/changelog.d/features/6879-default-reasoning-effort.md +++ /dev/null @@ -1 +0,0 @@ -- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) diff --git a/changelog.d/features/6880-connection-cache-override.md b/changelog.d/features/6880-connection-cache-override.md deleted file mode 100644 index 0f013bb59f..0000000000 --- a/changelog.d/features/6880-connection-cache-override.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) diff --git a/changelog.d/features/6915-free-rankings-auth-type-filter.md b/changelog.d/features/6915-free-rankings-auth-type-filter.md deleted file mode 100644 index 782449e384..0000000000 --- a/changelog.d/features/6915-free-rankings-auth-type-filter.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) diff --git a/changelog.d/features/6928-comfyui-base-url-field.md b/changelog.d/features/6928-comfyui-base-url-field.md deleted file mode 100644 index f578d96a45..0000000000 --- a/changelog.d/features/6928-comfyui-base-url-field.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) diff --git a/changelog.d/features/6976-openrouter-embeddings.md b/changelog.d/features/6976-openrouter-embeddings.md deleted file mode 100644 index 1997f3cd5a..0000000000 --- a/changelog.d/features/6976-openrouter-embeddings.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. diff --git a/changelog.d/features/6977-quota-auto-ping.md b/changelog.d/features/6977-quota-auto-ping.md deleted file mode 100644 index 694f4fbf89..0000000000 --- a/changelog.d/features/6977-quota-auto-ping.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) diff --git a/changelog.d/features/7013-grok-build-browser-login.md b/changelog.d/features/7013-grok-build-browser-login.md deleted file mode 100644 index b423709e76..0000000000 --- a/changelog.d/features/7013-grok-build-browser-login.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) diff --git a/changelog.d/features/7023-optional-enum-null-sentinel.md b/changelog.d/features/7023-optional-enum-null-sentinel.md deleted file mode 100644 index 965cb05307..0000000000 --- a/changelog.d/features/7023-optional-enum-null-sentinel.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) diff --git a/changelog.d/features/7034-x-goog-api-key-client-auth.md b/changelog.d/features/7034-x-goog-api-key-client-auth.md deleted file mode 100644 index 7228d880e6..0000000000 --- a/changelog.d/features/7034-x-goog-api-key-client-auth.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). diff --git a/changelog.d/features/7075-freemodel-quota-tracking.md b/changelog.d/features/7075-freemodel-quota-tracking.md deleted file mode 100644 index ba99b5f76b..0000000000 --- a/changelog.d/features/7075-freemodel-quota-tracking.md +++ /dev/null @@ -1 +0,0 @@ -- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. diff --git a/changelog.d/features/7079-free-proxy-autosync.md b/changelog.d/features/7079-free-proxy-autosync.md deleted file mode 100644 index b4d70e1701..0000000000 --- a/changelog.d/features/7079-free-proxy-autosync.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). diff --git a/changelog.d/features/7209-kiro-gpt56-family.md b/changelog.d/features/7209-kiro-gpt56-family.md deleted file mode 100644 index eed9627975..0000000000 --- a/changelog.d/features/7209-kiro-gpt56-family.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) diff --git a/changelog.d/features/7210-codex-plan-labels.md b/changelog.d/features/7210-codex-plan-labels.md deleted file mode 100644 index 0df8e21855..0000000000 --- a/changelog.d/features/7210-codex-plan-labels.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) diff --git a/changelog.d/features/7211-reorder-connections-by-availability.md b/changelog.d/features/7211-reorder-connections-by-availability.md deleted file mode 100644 index 54e302a369..0000000000 --- a/changelog.d/features/7211-reorder-connections-by-availability.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) diff --git a/changelog.d/features/7213-usage-extended-periods.md b/changelog.d/features/7213-usage-extended-periods.md deleted file mode 100644 index 704c08e147..0000000000 --- a/changelog.d/features/7213-usage-extended-periods.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) diff --git a/changelog.d/features/7223-github-copilot-claude-native-messages.md b/changelog.d/features/7223-github-copilot-claude-native-messages.md deleted file mode 100644 index 7885ba5596..0000000000 --- a/changelog.d/features/7223-github-copilot-claude-native-messages.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) diff --git a/changelog.d/features/7228-antigravity-reasoning-effort-overrides.md b/changelog.d/features/7228-antigravity-reasoning-effort-overrides.md deleted file mode 100644 index a52174b2b1..0000000000 --- a/changelog.d/features/7228-antigravity-reasoning-effort-overrides.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) diff --git a/changelog.d/features/7238-xai-grok-imagine-video.md b/changelog.d/features/7238-xai-grok-imagine-video.md deleted file mode 100644 index 9cac2f18b3..0000000000 --- a/changelog.d/features/7238-xai-grok-imagine-video.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) diff --git a/changelog.d/features/7241-grok-build-cli-setup.md b/changelog.d/features/7241-grok-build-cli-setup.md deleted file mode 100644 index 1e8c6bee5a..0000000000 --- a/changelog.d/features/7241-grok-build-cli-setup.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) diff --git a/changelog.d/features/7246-chenzk-provider.md b/changelog.d/features/7246-chenzk-provider.md deleted file mode 100644 index cc39d66de6..0000000000 --- a/changelog.d/features/7246-chenzk-provider.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) diff --git a/changelog.d/features/7251-provider-quota-visibility.md b/changelog.d/features/7251-provider-quota-visibility.md deleted file mode 100644 index 9969596245..0000000000 --- a/changelog.d/features/7251-provider-quota-visibility.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) diff --git a/changelog.d/features/7274-generic-session-affinity.md b/changelog.d/features/7274-generic-session-affinity.md deleted file mode 100644 index 46b950a8c9..0000000000 --- a/changelog.d/features/7274-generic-session-affinity.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). diff --git a/changelog.d/features/7286-geminiweb-tool-calling.md b/changelog.d/features/7286-geminiweb-tool-calling.md deleted file mode 100644 index 47ad9f5a52..0000000000 --- a/changelog.d/features/7286-geminiweb-tool-calling.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). diff --git a/changelog.d/features/7318-router-eval-harness.md b/changelog.d/features/7318-router-eval-harness.md deleted file mode 100644 index f88326e9e0..0000000000 --- a/changelog.d/features/7318-router-eval-harness.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). diff --git a/changelog.d/features/7333-pluggable-service-providers.md b/changelog.d/features/7333-pluggable-service-providers.md deleted file mode 100644 index 18dc0b2d75..0000000000 --- a/changelog.d/features/7333-pluggable-service-providers.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). diff --git a/changelog.d/features/7339-intercept-fetch-wiring.md b/changelog.d/features/7339-intercept-fetch-wiring.md deleted file mode 100644 index 19865e32c0..0000000000 --- a/changelog.d/features/7339-intercept-fetch-wiring.md +++ /dev/null @@ -1 +0,0 @@ -- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) diff --git a/changelog.d/features/7361-confirm-remove-account.md b/changelog.d/features/7361-confirm-remove-account.md deleted file mode 100644 index e6b824237e..0000000000 --- a/changelog.d/features/7361-confirm-remove-account.md +++ /dev/null @@ -1 +0,0 @@ -- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) diff --git a/changelog.d/features/7399-xai-oauth-pkce.md b/changelog.d/features/7399-xai-oauth-pkce.md deleted file mode 100644 index 7057b62489..0000000000 --- a/changelog.d/features/7399-xai-oauth-pkce.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 diff --git a/changelog.d/features/7530-compression-guidance.md b/changelog.d/features/7530-compression-guidance.md deleted file mode 100644 index 10a6593049..0000000000 --- a/changelog.d/features/7530-compression-guidance.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). diff --git a/changelog.d/features/7546-ghe-copilot.md b/changelog.d/features/7546-ghe-copilot.md deleted file mode 100644 index fadd45ddde..0000000000 --- a/changelog.d/features/7546-ghe-copilot.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) diff --git a/changelog.d/features/7567-grokweb-ua-hint.md b/changelog.d/features/7567-grokweb-ua-hint.md deleted file mode 100644 index 6370085f54..0000000000 --- a/changelog.d/features/7567-grokweb-ua-hint.md +++ /dev/null @@ -1 +0,0 @@ -- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) diff --git a/changelog.d/features/7601-lmstudio-embeddings.md b/changelog.d/features/7601-lmstudio-embeddings.md deleted file mode 100644 index 1fa73eb4af..0000000000 --- a/changelog.d/features/7601-lmstudio-embeddings.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. diff --git a/changelog.d/features/7622-noauth-autocombo-exclude.md b/changelog.d/features/7622-noauth-autocombo-exclude.md deleted file mode 100644 index a7a61cebaf..0000000000 --- a/changelog.d/features/7622-noauth-autocombo-exclude.md +++ /dev/null @@ -1 +0,0 @@ -- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). diff --git a/changelog.d/features/7643-proxy-ui-qol.md b/changelog.d/features/7643-proxy-ui-qol.md deleted file mode 100644 index 2959a03631..0000000000 --- a/changelog.d/features/7643-proxy-ui-qol.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). diff --git a/changelog.d/features/7678-zai-web-model-discovery.md b/changelog.d/features/7678-zai-web-model-discovery.md deleted file mode 100644 index d8d81c30aa..0000000000 --- a/changelog.d/features/7678-zai-web-model-discovery.md +++ /dev/null @@ -1 +0,0 @@ -- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. diff --git a/changelog.d/features/7687-perplexity-refresh.md b/changelog.d/features/7687-perplexity-refresh.md deleted file mode 100644 index 8444a1a320..0000000000 --- a/changelog.d/features/7687-perplexity-refresh.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun diff --git a/changelog.d/features/7694-reasoning-supported-efforts.md b/changelog.d/features/7694-reasoning-supported-efforts.md deleted file mode 100644 index 9d0656de29..0000000000 --- a/changelog.d/features/7694-reasoning-supported-efforts.md +++ /dev/null @@ -1 +0,0 @@ -- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. diff --git a/changelog.d/features/7775-kimi-provider-card-highlight.md b/changelog.d/features/7775-kimi-provider-card-highlight.md deleted file mode 100644 index 7f67d9fea9..0000000000 --- a/changelog.d/features/7775-kimi-provider-card-highlight.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). diff --git a/changelog.d/features/7818-custom-provider-tier.md b/changelog.d/features/7818-custom-provider-tier.md deleted file mode 100644 index 23d7d9a538..0000000000 --- a/changelog.d/features/7818-custom-provider-tier.md +++ /dev/null @@ -1 +0,0 @@ -- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) diff --git a/changelog.d/features/7819-auto-candidate-control.md b/changelog.d/features/7819-auto-candidate-control.md deleted file mode 100644 index c06853deeb..0000000000 --- a/changelog.d/features/7819-auto-candidate-control.md +++ /dev/null @@ -1 +0,0 @@ -- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). diff --git a/changelog.d/features/7872-m365-tone-model-variants.md b/changelog.d/features/7872-m365-tone-model-variants.md deleted file mode 100644 index 5492efae1d..0000000000 --- a/changelog.d/features/7872-m365-tone-model-variants.md +++ /dev/null @@ -1 +0,0 @@ -- feat(providers): copilot-m365-web tone-selected model variants (#7872) diff --git a/changelog.d/features/7879-numeric-helpers-foundation.md b/changelog.d/features/7879-numeric-helpers-foundation.md deleted file mode 100644 index c49b2f4453..0000000000 --- a/changelog.d/features/7879-numeric-helpers-foundation.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) diff --git a/changelog.d/features/7895-mcp-connect-scope-binding.md b/changelog.d/features/7895-mcp-connect-scope-binding.md deleted file mode 100644 index 1959255d46..0000000000 --- a/changelog.d/features/7895-mcp-connect-scope-binding.md +++ /dev/null @@ -1 +0,0 @@ -- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). diff --git a/changelog.d/features/7937-provider-account-search-pagination.md b/changelog.d/features/7937-provider-account-search-pagination.md deleted file mode 100644 index 8c8ece2370..0000000000 --- a/changelog.d/features/7937-provider-account-search-pagination.md +++ /dev/null @@ -1 +0,0 @@ -- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) diff --git a/changelog.d/features/8019-grok-web-cloudflare-classification.md b/changelog.d/features/8019-grok-web-cloudflare-classification.md deleted file mode 100644 index 854e013323..0000000000 --- a/changelog.d/features/8019-grok-web-cloudflare-classification.md +++ /dev/null @@ -1 +0,0 @@ -- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) diff --git a/changelog.d/features/8033-ccr-protocol-instruction.md b/changelog.d/features/8033-ccr-protocol-instruction.md deleted file mode 100644 index 74ff3ffcd1..0000000000 --- a/changelog.d/features/8033-ccr-protocol-instruction.md +++ /dev/null @@ -1 +0,0 @@ -- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) diff --git a/changelog.d/features/8034-compression-exclusions.md b/changelog.d/features/8034-compression-exclusions.md deleted file mode 100644 index fb2a9e670a..0000000000 --- a/changelog.d/features/8034-compression-exclusions.md +++ /dev/null @@ -1 +0,0 @@ -- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) diff --git a/changelog.d/features/8038-zhcn-terminology-visual-qa.md b/changelog.d/features/8038-zhcn-terminology-visual-qa.md deleted file mode 100644 index 287b21dedc..0000000000 --- a/changelog.d/features/8038-zhcn-terminology-visual-qa.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). diff --git a/changelog.d/features/8051-codex-quota-latent-windows.md b/changelog.d/features/8051-codex-quota-latent-windows.md deleted file mode 100644 index cffc367008..0000000000 --- a/changelog.d/features/8051-codex-quota-latent-windows.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) diff --git a/changelog.d/features/8099-fishaudio-tts-provider.md b/changelog.d/features/8099-fishaudio-tts-provider.md deleted file mode 100644 index af30808d8f..0000000000 --- a/changelog.d/features/8099-fishaudio-tts-provider.md +++ /dev/null @@ -1 +0,0 @@ -- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) diff --git a/changelog.d/features/8122-codex-reference-image-edits.md b/changelog.d/features/8122-codex-reference-image-edits.md deleted file mode 100644 index 9701708dd5..0000000000 --- a/changelog.d/features/8122-codex-reference-image-edits.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 diff --git a/changelog.d/features/8142-empty-catch-convention.md b/changelog.d/features/8142-empty-catch-convention.md deleted file mode 100644 index 5d38572dc3..0000000000 --- a/changelog.d/features/8142-empty-catch-convention.md +++ /dev/null @@ -1 +0,0 @@ -- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) diff --git a/changelog.d/features/8249-call-logs-session-tag.md b/changelog.d/features/8249-call-logs-session-tag.md deleted file mode 100644 index d747081fe8..0000000000 --- a/changelog.d/features/8249-call-logs-session-tag.md +++ /dev/null @@ -1 +0,0 @@ -- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) diff --git a/changelog.d/features/8297-web-fetch-quota-aware-fallback.md b/changelog.d/features/8297-web-fetch-quota-aware-fallback.md deleted file mode 100644 index c916cf1767..0000000000 --- a/changelog.d/features/8297-web-fetch-quota-aware-fallback.md +++ /dev/null @@ -1 +0,0 @@ -- feat(api): quota-aware fallback routing for web-fetch providers (#8297) diff --git a/changelog.d/features/8347-cliproxy-reasoning-levels.md b/changelog.d/features/8347-cliproxy-reasoning-levels.md deleted file mode 100644 index b75cb72687..0000000000 --- a/changelog.d/features/8347-cliproxy-reasoning-levels.md +++ /dev/null @@ -1 +0,0 @@ -- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) diff --git a/changelog.d/features/8471-xai-oauth-weekly-quota.md b/changelog.d/features/8471-xai-oauth-weekly-quota.md deleted file mode 100644 index 7b017bc554..0000000000 --- a/changelog.d/features/8471-xai-oauth-weekly-quota.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb diff --git a/changelog.d/features/8513-backup-schedule-execution.md b/changelog.d/features/8513-backup-schedule-execution.md deleted file mode 100644 index 249a0da309..0000000000 --- a/changelog.d/features/8513-backup-schedule-execution.md +++ /dev/null @@ -1 +0,0 @@ -- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher diff --git a/changelog.d/features/8612-auto-bank-ratchet-shrinks.md b/changelog.d/features/8612-auto-bank-ratchet-shrinks.md deleted file mode 100644 index 66eec7b2d5..0000000000 --- a/changelog.d/features/8612-auto-bank-ratchet-shrinks.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW diff --git a/changelog.d/features/8759-firecrawl-provider-quota.md b/changelog.d/features/8759-firecrawl-provider-quota.md deleted file mode 100644 index 8849c3fb8f..0000000000 --- a/changelog.d/features/8759-firecrawl-provider-quota.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb diff --git a/changelog.d/features/8814-firecrawl-search.md b/changelog.d/features/8814-firecrawl-search.md deleted file mode 100644 index eab6887919..0000000000 --- a/changelog.d/features/8814-firecrawl-search.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb diff --git a/changelog.d/features/adobe-firefly-reference-images.md b/changelog.d/features/adobe-firefly-reference-images.md deleted file mode 100644 index 5c889d9a76..0000000000 --- a/changelog.d/features/adobe-firefly-reference-images.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). diff --git a/changelog.d/features/homolog-e2e-suite.md b/changelog.d/features/homolog-e2e-suite.md deleted file mode 100644 index b2c4637d66..0000000000 --- a/changelog.d/features/homolog-e2e-suite.md +++ /dev/null @@ -1 +0,0 @@ -- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist diff --git a/changelog.d/features/local-corpus-context.md b/changelog.d/features/local-corpus-context.md deleted file mode 100644 index 29aa187f17..0000000000 --- a/changelog.d/features/local-corpus-context.md +++ /dev/null @@ -1 +0,0 @@ -- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. diff --git a/changelog.d/features/notion-web-available-models.md b/changelog.d/features/notion-web-available-models.md deleted file mode 100644 index ed73e21a55..0000000000 --- a/changelog.d/features/notion-web-available-models.md +++ /dev/null @@ -1 +0,0 @@ -- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) diff --git a/changelog.d/features/provider-quota-connection-visibility.md b/changelog.d/features/provider-quota-connection-visibility.md deleted file mode 100644 index 46e18fd848..0000000000 --- a/changelog.d/features/provider-quota-connection-visibility.md +++ /dev/null @@ -1,3 +0,0 @@ -- Provider connections can now be shown or hidden individually on the Provider Quota page. The - visibility setting is available on each account in the provider detail view and does not affect - routing or account activation. diff --git a/changelog.d/features/ru-readme-full-translation.md b/changelog.d/features/ru-readme-full-translation.md deleted file mode 100644 index 2e6b612210..0000000000 --- a/changelog.d/features/ru-readme-full-translation.md +++ /dev/null @@ -1 +0,0 @@ -- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). diff --git a/changelog.d/fixes/1037-vercel-relay-sso-protection-check.md b/changelog.d/fixes/1037-vercel-relay-sso-protection-check.md deleted file mode 100644 index e03d00dd02..0000000000 --- a/changelog.d/fixes/1037-vercel-relay-sso-protection-check.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) diff --git a/changelog.d/fixes/1253-kiro-sso-cache-clientid.md b/changelog.d/fixes/1253-kiro-sso-cache-clientid.md deleted file mode 100644 index 091d8a223c..0000000000 --- a/changelog.d/fixes/1253-kiro-sso-cache-clientid.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). diff --git a/changelog.d/fixes/1382-streaming-empty-content-block.md b/changelog.d/fixes/1382-streaming-empty-content-block.md deleted file mode 100644 index c224cd2991..0000000000 --- a/changelog.d/fixes/1382-streaming-empty-content-block.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). diff --git a/changelog.d/fixes/1556-openai-regex-lookaround.md b/changelog.d/fixes/1556-openai-regex-lookaround.md deleted file mode 100644 index 7045d0917d..0000000000 --- a/changelog.d/fixes/1556-openai-regex-lookaround.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) diff --git a/changelog.d/fixes/180-3980-responses-completed-tool-calls.md b/changelog.d/fixes/180-3980-responses-completed-tool-calls.md deleted file mode 100644 index f9556e0138..0000000000 --- a/changelog.d/fixes/180-3980-responses-completed-tool-calls.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) diff --git a/changelog.d/fixes/1809-mitm-stop-dns-before-kill.md b/changelog.d/fixes/1809-mitm-stop-dns-before-kill.md deleted file mode 100644 index 06e42e461c..0000000000 --- a/changelog.d/fixes/1809-mitm-stop-dns-before-kill.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). diff --git a/changelog.d/fixes/1811-composer-space-sep.md b/changelog.d/fixes/1811-composer-space-sep.md deleted file mode 100644 index 856fab9e17..0000000000 --- a/changelog.d/fixes/1811-composer-space-sep.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) diff --git a/changelog.d/fixes/1904-custom-model-vision-toggle.md b/changelog.d/fixes/1904-custom-model-vision-toggle.md deleted file mode 100644 index 85fd14aff1..0000000000 --- a/changelog.d/fixes/1904-custom-model-vision-toggle.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) diff --git a/changelog.d/fixes/1905-fusion-panel-oom.md b/changelog.d/fixes/1905-fusion-panel-oom.md deleted file mode 100644 index 68bc6dbfbc..0000000000 --- a/changelog.d/fixes/1905-fusion-panel-oom.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) diff --git a/changelog.d/fixes/2032-openai-compatible-check-404-warning.md b/changelog.d/fixes/2032-openai-compatible-check-404-warning.md deleted file mode 100644 index 5933bf065f..0000000000 --- a/changelog.d/fixes/2032-openai-compatible-check-404-warning.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) diff --git a/changelog.d/fixes/2057-combo-custom-provider-models.md b/changelog.d/fixes/2057-combo-custom-provider-models.md deleted file mode 100644 index b6b75b6256..0000000000 --- a/changelog.d/fixes/2057-combo-custom-provider-models.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) diff --git a/changelog.d/fixes/2413-preserve-agent-headers.md b/changelog.d/fixes/2413-preserve-agent-headers.md deleted file mode 100644 index 6353f5dd77..0000000000 --- a/changelog.d/fixes/2413-preserve-agent-headers.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) diff --git a/changelog.d/fixes/2461-antigravity-streaming-403-raw-bytes.md b/changelog.d/fixes/2461-antigravity-streaming-403-raw-bytes.md deleted file mode 100644 index 84cf50b3de..0000000000 --- a/changelog.d/fixes/2461-antigravity-streaming-403-raw-bytes.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool diff --git a/changelog.d/fixes/2482-minimax-image-provider.md b/changelog.d/fixes/2482-minimax-image-provider.md deleted file mode 100644 index d6fcbbbc4b..0000000000 --- a/changelog.d/fixes/2482-minimax-image-provider.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) diff --git a/changelog.d/fixes/2493-better-sqlite3-abi-validation.md b/changelog.d/fixes/2493-better-sqlite3-abi-validation.md deleted file mode 100644 index dba246809d..0000000000 --- a/changelog.d/fixes/2493-better-sqlite3-abi-validation.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) diff --git a/changelog.d/fixes/2540-gpt5-tools-reasoning-effort.md b/changelog.d/fixes/2540-gpt5-tools-reasoning-effort.md deleted file mode 100644 index bdd460cfcb..0000000000 --- a/changelog.d/fixes/2540-gpt5-tools-reasoning-effort.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta diff --git a/changelog.d/fixes/5716-proxy-pool-relayauth-dropped.md b/changelog.d/fixes/5716-proxy-pool-relayauth-dropped.md deleted file mode 100644 index 72d11d1f3a..0000000000 --- a/changelog.d/fixes/5716-proxy-pool-relayauth-dropped.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) diff --git a/changelog.d/fixes/6142-6142-devin-unified-api.md b/changelog.d/fixes/6142-6142-devin-unified-api.md deleted file mode 100644 index bda88bd4c8..0000000000 --- a/changelog.d/fixes/6142-6142-devin-unified-api.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) diff --git a/changelog.d/fixes/6271-baidu-qianfan-website-urls.md b/changelog.d/fixes/6271-baidu-qianfan-website-urls.md deleted file mode 100644 index 7102cbd75b..0000000000 --- a/changelog.d/fixes/6271-baidu-qianfan-website-urls.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore diff --git a/changelog.d/fixes/6272-6272-mimo-proxy.md b/changelog.d/fixes/6272-6272-mimo-proxy.md deleted file mode 100644 index 37b11868be..0000000000 --- a/changelog.d/fixes/6272-6272-mimo-proxy.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) diff --git a/changelog.d/fixes/6276-toolcall-args-logs.md b/changelog.d/fixes/6276-toolcall-args-logs.md deleted file mode 100644 index 90b6bde61b..0000000000 --- a/changelog.d/fixes/6276-toolcall-args-logs.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) diff --git a/changelog.d/fixes/6280-lmarena-arena-modernize.md b/changelog.d/fixes/6280-lmarena-arena-modernize.md deleted file mode 100644 index 4ba53979bc..0000000000 --- a/changelog.d/fixes/6280-lmarena-arena-modernize.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun diff --git a/changelog.d/fixes/6308-web-model-discovery.md b/changelog.d/fixes/6308-web-model-discovery.md deleted file mode 100644 index a452c1ae73..0000000000 --- a/changelog.d/fixes/6308-web-model-discovery.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). diff --git a/changelog.d/fixes/6323-log-detail-stale-reopen.md b/changelog.d/fixes/6323-log-detail-stale-reopen.md deleted file mode 100644 index ec1c53ca2f..0000000000 --- a/changelog.d/fixes/6323-log-detail-stale-reopen.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). diff --git a/changelog.d/fixes/6330-sensenova-token-plan.md b/changelog.d/fixes/6330-sensenova-token-plan.md deleted file mode 100644 index 3ef26dea2b..0000000000 --- a/changelog.d/fixes/6330-sensenova-token-plan.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). diff --git a/changelog.d/fixes/6343-6343-v0web-creds.md b/changelog.d/fixes/6343-6343-v0web-creds.md deleted file mode 100644 index e939d0df24..0000000000 --- a/changelog.d/fixes/6343-6343-v0web-creds.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) diff --git a/changelog.d/fixes/6377-6377-agentrouter-key.md b/changelog.d/fixes/6377-6377-agentrouter-key.md deleted file mode 100644 index c9bc47e827..0000000000 --- a/changelog.d/fixes/6377-6377-agentrouter-key.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) diff --git a/changelog.d/fixes/6401-6401-usage-migrations.md b/changelog.d/fixes/6401-6401-usage-migrations.md deleted file mode 100644 index 3d623f9dc6..0000000000 --- a/changelog.d/fixes/6401-6401-usage-migrations.md +++ /dev/null @@ -1 +0,0 @@ -- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) diff --git a/changelog.d/fixes/6409-6409-build-ram.md b/changelog.d/fixes/6409-6409-build-ram.md deleted file mode 100644 index 4baeb797a6..0000000000 --- a/changelog.d/fixes/6409-6409-build-ram.md +++ /dev/null @@ -1 +0,0 @@ -- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) diff --git a/changelog.d/fixes/6479-6479-compression-pipeline.md b/changelog.d/fixes/6479-6479-compression-pipeline.md deleted file mode 100644 index dba6094066..0000000000 --- a/changelog.d/fixes/6479-6479-compression-pipeline.md +++ /dev/null @@ -1 +0,0 @@ -- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) diff --git a/changelog.d/fixes/6524-6524-reasoning-buffer-clamp.md b/changelog.d/fixes/6524-6524-reasoning-buffer-clamp.md deleted file mode 100644 index 9f551de90c..0000000000 --- a/changelog.d/fixes/6524-6524-reasoning-buffer-clamp.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) diff --git a/changelog.d/fixes/6538-tier-flow-svg-public.md b/changelog.d/fixes/6538-tier-flow-svg-public.md deleted file mode 100644 index e3d3f76cef..0000000000 --- a/changelog.d/fixes/6538-tier-flow-svg-public.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). diff --git a/changelog.d/fixes/6557-6557-disabled-provider.md b/changelog.d/fixes/6557-6557-disabled-provider.md deleted file mode 100644 index aa924555d3..0000000000 --- a/changelog.d/fixes/6557-6557-disabled-provider.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). diff --git a/changelog.d/fixes/6586-preserve-server-tool-names.md b/changelog.d/fixes/6586-preserve-server-tool-names.md deleted file mode 100644 index 62ee75c234..0000000000 --- a/changelog.d/fixes/6586-preserve-server-tool-names.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). diff --git a/changelog.d/fixes/6612-combo-diagnostics-header-bytestring-crash.md b/changelog.d/fixes/6612-combo-diagnostics-header-bytestring-crash.md deleted file mode 100644 index 77f12ced1f..0000000000 --- a/changelog.d/fixes/6612-combo-diagnostics-header-bytestring-crash.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) diff --git a/changelog.d/fixes/6623-6623-mimo-502-messages.md b/changelog.d/fixes/6623-6623-mimo-502-messages.md deleted file mode 100644 index 5d476c21ef..0000000000 --- a/changelog.d/fixes/6623-6623-mimo-502-messages.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) diff --git a/changelog.d/fixes/6628-6628-sqljs-adapter.md b/changelog.d/fixes/6628-6628-sqljs-adapter.md deleted file mode 100644 index 55d6a3ce9a..0000000000 --- a/changelog.d/fixes/6628-6628-sqljs-adapter.md +++ /dev/null @@ -1,2 +0,0 @@ -- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) -- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) diff --git a/changelog.d/fixes/6632-probe-restore-loop-cycle-breaker.md b/changelog.d/fixes/6632-probe-restore-loop-cycle-breaker.md deleted file mode 100644 index 45094d3742..0000000000 --- a/changelog.d/fixes/6632-probe-restore-loop-cycle-breaker.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). diff --git a/changelog.d/fixes/6634-6634-testmasking-selfref.md b/changelog.d/fixes/6634-6634-testmasking-selfref.md deleted file mode 100644 index 2982803f5a..0000000000 --- a/changelog.d/fixes/6634-6634-testmasking-selfref.md +++ /dev/null @@ -1 +0,0 @@ -- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) diff --git a/changelog.d/fixes/6637-6637-combo-kimi-fallback.md b/changelog.d/fixes/6637-6637-combo-kimi-fallback.md deleted file mode 100644 index be7cd2ed0b..0000000000 --- a/changelog.d/fixes/6637-6637-combo-kimi-fallback.md +++ /dev/null @@ -1 +0,0 @@ -- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) diff --git a/changelog.d/fixes/6647-winget-claude-detect.md b/changelog.d/fixes/6647-winget-claude-detect.md deleted file mode 100644 index c0ffef1324..0000000000 --- a/changelog.d/fixes/6647-winget-claude-detect.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). diff --git a/changelog.d/fixes/6675-remove-obsolete-providers.md b/changelog.d/fixes/6675-remove-obsolete-providers.md deleted file mode 100644 index 4c4f4bcf1c..0000000000 --- a/changelog.d/fixes/6675-remove-obsolete-providers.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). diff --git a/changelog.d/fixes/6698-count-gate-rejected-usage.md b/changelog.d/fixes/6698-count-gate-rejected-usage.md deleted file mode 100644 index bb1288c407..0000000000 --- a/changelog.d/fixes/6698-count-gate-rejected-usage.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). diff --git a/changelog.d/fixes/6699-jules-chat-executor-misroute.md b/changelog.d/fixes/6699-jules-chat-executor-misroute.md deleted file mode 100644 index 58823d5879..0000000000 --- a/changelog.d/fixes/6699-jules-chat-executor-misroute.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) diff --git a/changelog.d/fixes/6704-unwrap-bare-function-tool.md b/changelog.d/fixes/6704-unwrap-bare-function-tool.md deleted file mode 100644 index 85b21b7c5b..0000000000 --- a/changelog.d/fixes/6704-unwrap-bare-function-tool.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) diff --git a/changelog.d/fixes/6706-codex-oauth-bare-email-dedup.md b/changelog.d/fixes/6706-codex-oauth-bare-email-dedup.md deleted file mode 100644 index 4eca2c7828..0000000000 --- a/changelog.d/fixes/6706-codex-oauth-bare-email-dedup.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) diff --git a/changelog.d/fixes/6710-codex-200-sse-capacity-error.md b/changelog.d/fixes/6710-codex-200-sse-capacity-error.md deleted file mode 100644 index e84653d7bd..0000000000 --- a/changelog.d/fixes/6710-codex-200-sse-capacity-error.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) diff --git a/changelog.d/fixes/6712-volcengine-kimi-max-tokens.md b/changelog.d/fixes/6712-volcengine-kimi-max-tokens.md deleted file mode 100644 index 29586d549c..0000000000 --- a/changelog.d/fixes/6712-volcengine-kimi-max-tokens.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) diff --git a/changelog.d/fixes/6713-antigravity-abort-finish-reason.md b/changelog.d/fixes/6713-antigravity-abort-finish-reason.md deleted file mode 100644 index f94984faf6..0000000000 --- a/changelog.d/fixes/6713-antigravity-abort-finish-reason.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) diff --git a/changelog.d/fixes/6714-reasoning-buffer-cap-aware.md b/changelog.d/fixes/6714-reasoning-buffer-cap-aware.md deleted file mode 100644 index a67b36333c..0000000000 --- a/changelog.d/fixes/6714-reasoning-buffer-cap-aware.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev diff --git a/changelog.d/fixes/6717-cli-health-monitoring-route.md b/changelog.d/fixes/6717-cli-health-monitoring-route.md deleted file mode 100644 index 80e5ad7ec7..0000000000 --- a/changelog.d/fixes/6717-cli-health-monitoring-route.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. diff --git a/changelog.d/fixes/6718-reasoningcontrols-case-collision.md b/changelog.d/fixes/6718-reasoningcontrols-case-collision.md deleted file mode 100644 index 4c4449755f..0000000000 --- a/changelog.d/fixes/6718-reasoningcontrols-case-collision.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) diff --git a/changelog.d/fixes/6720-turbopack-agentskills-warning.md b/changelog.d/fixes/6720-turbopack-agentskills-warning.md deleted file mode 100644 index aa9fc2e42b..0000000000 --- a/changelog.d/fixes/6720-turbopack-agentskills-warning.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). diff --git a/changelog.d/fixes/6721-codex-spark-image-drop.md b/changelog.d/fixes/6721-codex-spark-image-drop.md deleted file mode 100644 index d814d8bd39..0000000000 --- a/changelog.d/fixes/6721-codex-spark-image-drop.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). diff --git a/changelog.d/fixes/6722-quota-card-fixed-order.md b/changelog.d/fixes/6722-quota-card-fixed-order.md deleted file mode 100644 index ea2d2f7bbd..0000000000 --- a/changelog.d/fixes/6722-quota-card-fixed-order.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. diff --git a/changelog.d/fixes/6723-i18n-pt-br-backfill.md b/changelog.d/fixes/6723-i18n-pt-br-backfill.md deleted file mode 100644 index aca0c58e24..0000000000 --- a/changelog.d/fixes/6723-i18n-pt-br-backfill.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). diff --git a/changelog.d/fixes/6725-lazy-ioredis-mcp.md b/changelog.d/fixes/6725-lazy-ioredis-mcp.md deleted file mode 100644 index ba6238f5ec..0000000000 --- a/changelog.d/fixes/6725-lazy-ioredis-mcp.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). diff --git a/changelog.d/fixes/6726-kiro-adaptive-thinking-allowlist.md b/changelog.d/fixes/6726-kiro-adaptive-thinking-allowlist.md deleted file mode 100644 index e31c103661..0000000000 --- a/changelog.d/fixes/6726-kiro-adaptive-thinking-allowlist.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. diff --git a/changelog.d/fixes/6729-cursor-subagent-strip-cloud-base.md b/changelog.d/fixes/6729-cursor-subagent-strip-cloud-base.md deleted file mode 100644 index 4cd79fd8a3..0000000000 --- a/changelog.d/fixes/6729-cursor-subagent-strip-cloud-base.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) diff --git a/changelog.d/fixes/6730-glm-split-tool-name.md b/changelog.d/fixes/6730-glm-split-tool-name.md deleted file mode 100644 index ad807f6272..0000000000 --- a/changelog.d/fixes/6730-glm-split-tool-name.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) diff --git a/changelog.d/fixes/6731-apikey-429-quota-exhausted.md b/changelog.d/fixes/6731-apikey-429-quota-exhausted.md deleted file mode 100644 index bdfabc45ef..0000000000 --- a/changelog.d/fixes/6731-apikey-429-quota-exhausted.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. diff --git a/changelog.d/fixes/6732-fp-pinned-combo-resolve.md b/changelog.d/fixes/6732-fp-pinned-combo-resolve.md deleted file mode 100644 index 47f790681c..0000000000 --- a/changelog.d/fixes/6732-fp-pinned-combo-resolve.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. diff --git a/changelog.d/fixes/6735-responses-commentary-event-frame.md b/changelog.d/fixes/6735-responses-commentary-event-frame.md deleted file mode 100644 index 6dce5931c9..0000000000 --- a/changelog.d/fixes/6735-responses-commentary-event-frame.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). diff --git a/changelog.d/fixes/6741-compression-preview-token-reconcile.md b/changelog.d/fixes/6741-compression-preview-token-reconcile.md deleted file mode 100644 index 122a354265..0000000000 --- a/changelog.d/fixes/6741-compression-preview-token-reconcile.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. diff --git a/changelog.d/fixes/6742-quota-preflight-coverage.md b/changelog.d/fixes/6742-quota-preflight-coverage.md deleted file mode 100644 index 45178354e4..0000000000 --- a/changelog.d/fixes/6742-quota-preflight-coverage.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). diff --git a/changelog.d/fixes/6743-reasoning-content-web-sse.md b/changelog.d/fixes/6743-reasoning-content-web-sse.md deleted file mode 100644 index 089a53d995..0000000000 --- a/changelog.d/fixes/6743-reasoning-content-web-sse.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). diff --git a/changelog.d/fixes/6757-rtk-enable-renderers-schema.md b/changelog.d/fixes/6757-rtk-enable-renderers-schema.md deleted file mode 100644 index a6aa1c910e..0000000000 --- a/changelog.d/fixes/6757-rtk-enable-renderers-schema.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). diff --git a/changelog.d/fixes/6759-cookie-provider-apikey-cap.md b/changelog.d/fixes/6759-cookie-provider-apikey-cap.md deleted file mode 100644 index 56fa315e97..0000000000 --- a/changelog.d/fixes/6759-cookie-provider-apikey-cap.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). diff --git a/changelog.d/fixes/6764-fusion-combo-ref.md b/changelog.d/fixes/6764-fusion-combo-ref.md deleted file mode 100644 index 403336afae..0000000000 --- a/changelog.d/fixes/6764-fusion-combo-ref.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) diff --git a/changelog.d/fixes/6766-6766-auto-update.md b/changelog.d/fixes/6766-6766-auto-update.md deleted file mode 100644 index ec08f4a65b..0000000000 --- a/changelog.d/fixes/6766-6766-auto-update.md +++ /dev/null @@ -1 +0,0 @@ -- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) diff --git a/changelog.d/fixes/6769-i18n-translate-pt-dashboard.md b/changelog.d/fixes/6769-i18n-translate-pt-dashboard.md deleted file mode 100644 index 590224dc79..0000000000 --- a/changelog.d/fixes/6769-i18n-translate-pt-dashboard.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). diff --git a/changelog.d/fixes/6772-6772-connid-model-400.md b/changelog.d/fixes/6772-6772-connid-model-400.md deleted file mode 100644 index 795c840317..0000000000 --- a/changelog.d/fixes/6772-6772-connid-model-400.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) diff --git a/changelog.d/fixes/6773-6773-nim-404.md b/changelog.d/fixes/6773-6773-nim-404.md deleted file mode 100644 index ba6d5e1543..0000000000 --- a/changelog.d/fixes/6773-6773-nim-404.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) diff --git a/changelog.d/fixes/6780-bump-codex-client-version.md b/changelog.d/fixes/6780-bump-codex-client-version.md deleted file mode 100644 index 634ded640e..0000000000 --- a/changelog.d/fixes/6780-bump-codex-client-version.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo diff --git a/changelog.d/fixes/6788-tia-dashboard-loader.md b/changelog.d/fixes/6788-tia-dashboard-loader.md deleted file mode 100644 index 50e6f4f06b..0000000000 --- a/changelog.d/fixes/6788-tia-dashboard-loader.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). diff --git a/changelog.d/fixes/6790-gemini-pdf-video-attachments.md b/changelog.d/fixes/6790-gemini-pdf-video-attachments.md deleted file mode 100644 index ad4cf383d9..0000000000 --- a/changelog.d/fixes/6790-gemini-pdf-video-attachments.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). diff --git a/changelog.d/fixes/6791-deepseek-web-done-after-finished.md b/changelog.d/fixes/6791-deepseek-web-done-after-finished.md deleted file mode 100644 index f7b161c4fd..0000000000 --- a/changelog.d/fixes/6791-deepseek-web-done-after-finished.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). diff --git a/changelog.d/fixes/6792-compression-put-all-catalog-engines.md b/changelog.d/fixes/6792-compression-put-all-catalog-engines.md deleted file mode 100644 index 813620e098..0000000000 --- a/changelog.d/fixes/6792-compression-put-all-catalog-engines.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). diff --git a/changelog.d/fixes/6794-electron-turbopack-symlinks.md b/changelog.d/fixes/6794-electron-turbopack-symlinks.md deleted file mode 100644 index 963e35e6bc..0000000000 --- a/changelog.d/fixes/6794-electron-turbopack-symlinks.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). diff --git a/changelog.d/fixes/6795-cursor-client-version-build-id.md b/changelog.d/fixes/6795-cursor-client-version-build-id.md deleted file mode 100644 index b82f2fbba2..0000000000 --- a/changelog.d/fixes/6795-cursor-client-version-build-id.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). diff --git a/changelog.d/fixes/6800-6800-listen-banner-early.md b/changelog.d/fixes/6800-6800-listen-banner-early.md deleted file mode 100644 index c53bae5d7f..0000000000 --- a/changelog.d/fixes/6800-6800-listen-banner-early.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) diff --git a/changelog.d/fixes/6803-6803-flaky-timing-tests.md b/changelog.d/fixes/6803-6803-flaky-timing-tests.md deleted file mode 100644 index 682b5b1887..0000000000 --- a/changelog.d/fixes/6803-6803-flaky-timing-tests.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) diff --git a/changelog.d/fixes/6805-strip-include-compact-responses.md b/changelog.d/fixes/6805-strip-include-compact-responses.md deleted file mode 100644 index 6c46a717a4..0000000000 --- a/changelog.d/fixes/6805-strip-include-compact-responses.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). diff --git a/changelog.d/fixes/6806-6806-claude-quota-data.md b/changelog.d/fixes/6806-6806-claude-quota-data.md deleted file mode 100644 index bbc9f76803..0000000000 --- a/changelog.d/fixes/6806-6806-claude-quota-data.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) diff --git a/changelog.d/fixes/6812-request-count-by-provider-date.md b/changelog.d/fixes/6812-request-count-by-provider-date.md deleted file mode 100644 index 503897954e..0000000000 --- a/changelog.d/fixes/6812-request-count-by-provider-date.md +++ /dev/null @@ -1 +0,0 @@ -- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) diff --git a/changelog.d/fixes/6817-ollama-cloud-weekly-quota.md b/changelog.d/fixes/6817-ollama-cloud-weekly-quota.md deleted file mode 100644 index 9ff2857cf5..0000000000 --- a/changelog.d/fixes/6817-ollama-cloud-weekly-quota.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. diff --git a/changelog.d/fixes/6821-budget-tokens-zero-gemini.md b/changelog.d/fixes/6821-budget-tokens-zero-gemini.md deleted file mode 100644 index 3886b4e6b3..0000000000 --- a/changelog.d/fixes/6821-budget-tokens-zero-gemini.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). diff --git a/changelog.d/fixes/6828-bootstrap-filter-empty-env.md b/changelog.d/fixes/6828-bootstrap-filter-empty-env.md deleted file mode 100644 index d4a6ca34ad..0000000000 --- a/changelog.d/fixes/6828-bootstrap-filter-empty-env.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). diff --git a/changelog.d/fixes/6829-classify-404-model-not-found.md b/changelog.d/fixes/6829-classify-404-model-not-found.md deleted file mode 100644 index 77a741377c..0000000000 --- a/changelog.d/fixes/6829-classify-404-model-not-found.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). diff --git a/changelog.d/fixes/6835-db-oom-probe-cyclebreaker.md b/changelog.d/fixes/6835-db-oom-probe-cyclebreaker.md deleted file mode 100644 index 3208171d3f..0000000000 --- a/changelog.d/fixes/6835-db-oom-probe-cyclebreaker.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). diff --git a/changelog.d/fixes/6854-6854-mcp-toolcount.md b/changelog.d/fixes/6854-6854-mcp-toolcount.md deleted file mode 100644 index 1e0ac6b1fe..0000000000 --- a/changelog.d/fixes/6854-6854-mcp-toolcount.md +++ /dev/null @@ -1 +0,0 @@ -- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) diff --git a/changelog.d/fixes/6856-usage-exact-cost-strict-validation.md b/changelog.d/fixes/6856-usage-exact-cost-strict-validation.md deleted file mode 100644 index abc5c3bc84..0000000000 --- a/changelog.d/fixes/6856-usage-exact-cost-strict-validation.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) diff --git a/changelog.d/fixes/6859-plugin-provider-id.md b/changelog.d/fixes/6859-plugin-provider-id.md deleted file mode 100644 index 9343798009..0000000000 --- a/changelog.d/fixes/6859-plugin-provider-id.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). diff --git a/changelog.d/fixes/6876-6876-cliproxy-modelmap.md b/changelog.d/fixes/6876-6876-cliproxy-modelmap.md deleted file mode 100644 index d28d68467b..0000000000 --- a/changelog.d/fixes/6876-6876-cliproxy-modelmap.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) diff --git a/changelog.d/fixes/6906-responses-usage-trailing.md b/changelog.d/fixes/6906-responses-usage-trailing.md deleted file mode 100644 index bfa9691b4b..0000000000 --- a/changelog.d/fixes/6906-responses-usage-trailing.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) diff --git a/changelog.d/fixes/6908-standalone-head-response-guard.md b/changelog.d/fixes/6908-standalone-head-response-guard.md deleted file mode 100644 index 3bb36703a6..0000000000 --- a/changelog.d/fixes/6908-standalone-head-response-guard.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) diff --git a/changelog.d/fixes/6911-quota-throttle-all-fetchers.md b/changelog.d/fixes/6911-quota-throttle-all-fetchers.md deleted file mode 100644 index 0983d10b27..0000000000 --- a/changelog.d/fixes/6911-quota-throttle-all-fetchers.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) diff --git a/changelog.d/fixes/6912-volcengine-max-tokens-rename.md b/changelog.d/fixes/6912-volcengine-max-tokens-rename.md deleted file mode 100644 index 88d6ac0e3d..0000000000 --- a/changelog.d/fixes/6912-volcengine-max-tokens-rename.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) diff --git a/changelog.d/fixes/6916-provider-limits-spacing-local.md b/changelog.d/fixes/6916-provider-limits-spacing-local.md deleted file mode 100644 index 2bfb988ee4..0000000000 --- a/changelog.d/fixes/6916-provider-limits-spacing-local.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) diff --git a/changelog.d/fixes/6925-embeddings-lan-noauth.md b/changelog.d/fixes/6925-embeddings-lan-noauth.md deleted file mode 100644 index 03bd51b6d1..0000000000 --- a/changelog.d/fixes/6925-embeddings-lan-noauth.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) diff --git a/changelog.d/fixes/6927-qwen-web-content-array.md b/changelog.d/fixes/6927-qwen-web-content-array.md deleted file mode 100644 index 5eff8b6ed9..0000000000 --- a/changelog.d/fixes/6927-qwen-web-content-array.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) diff --git a/changelog.d/fixes/6930-relay-checkratelimit-token-reuse.md b/changelog.d/fixes/6930-relay-checkratelimit-token-reuse.md deleted file mode 100644 index e52bb9d46a..0000000000 --- a/changelog.d/fixes/6930-relay-checkratelimit-token-reuse.md +++ /dev/null @@ -1 +0,0 @@ -- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) diff --git a/changelog.d/fixes/6932-codex-assistant-input-text-normalization.md b/changelog.d/fixes/6932-codex-assistant-input-text-normalization.md deleted file mode 100644 index 3ae7dc8dc9..0000000000 --- a/changelog.d/fixes/6932-codex-assistant-input-text-normalization.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) diff --git a/changelog.d/fixes/6935-muse-spark-attachments.md b/changelog.d/fixes/6935-muse-spark-attachments.md deleted file mode 100644 index e2a8f4d3ed..0000000000 --- a/changelog.d/fixes/6935-muse-spark-attachments.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) diff --git a/changelog.d/fixes/6936-providercard-audio-badge.md b/changelog.d/fixes/6936-providercard-audio-badge.md deleted file mode 100644 index 6b70fb4434..0000000000 --- a/changelog.d/fixes/6936-providercard-audio-badge.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) diff --git a/changelog.d/fixes/6939-lmstudio-models-guard.md b/changelog.d/fixes/6939-lmstudio-models-guard.md deleted file mode 100644 index 538a2e5769..0000000000 --- a/changelog.d/fixes/6939-lmstudio-models-guard.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) diff --git a/changelog.d/fixes/6943-gemini-thinking-none-effort.md b/changelog.d/fixes/6943-gemini-thinking-none-effort.md deleted file mode 100644 index 0c6f67f2b9..0000000000 --- a/changelog.d/fixes/6943-gemini-thinking-none-effort.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) diff --git a/changelog.d/fixes/6944-chatgpt-web-citation-backslash-escape.md b/changelog.d/fixes/6944-chatgpt-web-citation-backslash-escape.md deleted file mode 100644 index cefb3d8800..0000000000 --- a/changelog.d/fixes/6944-chatgpt-web-citation-backslash-escape.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl diff --git a/changelog.d/fixes/6947-tokenhealthcheck-provider-case.md b/changelog.d/fixes/6947-tokenhealthcheck-provider-case.md deleted file mode 100644 index d9b19fa4e9..0000000000 --- a/changelog.d/fixes/6947-tokenhealthcheck-provider-case.md +++ /dev/null @@ -1 +0,0 @@ -- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) diff --git a/changelog.d/fixes/6951-codex-optional-tool-params.md b/changelog.d/fixes/6951-codex-optional-tool-params.md deleted file mode 100644 index 2d634fd24c..0000000000 --- a/changelog.d/fixes/6951-codex-optional-tool-params.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) diff --git a/changelog.d/fixes/6952-commentary-translate-mode.md b/changelog.d/fixes/6952-commentary-translate-mode.md deleted file mode 100644 index 07dd100b32..0000000000 --- a/changelog.d/fixes/6952-commentary-translate-mode.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) diff --git a/changelog.d/fixes/6953-empty-signature-thinking-block.md b/changelog.d/fixes/6953-empty-signature-thinking-block.md deleted file mode 100644 index a95324f99a..0000000000 --- a/changelog.d/fixes/6953-empty-signature-thinking-block.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) diff --git a/changelog.d/fixes/6955-perplexity-web-empty-content.md b/changelog.d/fixes/6955-perplexity-web-empty-content.md deleted file mode 100644 index ac59619904..0000000000 --- a/changelog.d/fixes/6955-perplexity-web-empty-content.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) diff --git a/changelog.d/fixes/6975-6957-combo-builder-models.md b/changelog.d/fixes/6975-6957-combo-builder-models.md deleted file mode 100644 index 46f0154967..0000000000 --- a/changelog.d/fixes/6975-6957-combo-builder-models.md +++ /dev/null @@ -1,2 +0,0 @@ -- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). -- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). diff --git a/changelog.d/fixes/6984-hide-disabled-connections-combos.md b/changelog.d/fixes/6984-hide-disabled-connections-combos.md deleted file mode 100644 index 48d637549b..0000000000 --- a/changelog.d/fixes/6984-hide-disabled-connections-combos.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). diff --git a/changelog.d/fixes/6986-grok-cli-tools-cap.md b/changelog.d/fixes/6986-grok-cli-tools-cap.md deleted file mode 100644 index 8f38f0bc64..0000000000 --- a/changelog.d/fixes/6986-grok-cli-tools-cap.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) diff --git a/changelog.d/fixes/6996-duckduckgo-vqd-429-misclassified.md b/changelog.d/fixes/6996-duckduckgo-vqd-429-misclassified.md deleted file mode 100644 index 36b15a9cbd..0000000000 --- a/changelog.d/fixes/6996-duckduckgo-vqd-429-misclassified.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) diff --git a/changelog.d/fixes/6998-opencode-oc-free-tier-catalog.md b/changelog.d/fixes/6998-opencode-oc-free-tier-catalog.md deleted file mode 100644 index e5a3f5189b..0000000000 --- a/changelog.d/fixes/6998-opencode-oc-free-tier-catalog.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) diff --git a/changelog.d/fixes/7003-jetbrains-ai-loopback-connect.md b/changelog.d/fixes/7003-jetbrains-ai-loopback-connect.md deleted file mode 100644 index bc3b0a89c4..0000000000 --- a/changelog.d/fixes/7003-jetbrains-ai-loopback-connect.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) diff --git a/changelog.d/fixes/7005-adaptive-context-budget-dial.md b/changelog.d/fixes/7005-adaptive-context-budget-dial.md deleted file mode 100644 index 4b8e8aee5b..0000000000 --- a/changelog.d/fixes/7005-adaptive-context-budget-dial.md +++ /dev/null @@ -1 +0,0 @@ -- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) diff --git a/changelog.d/fixes/7022-opencode-go-quota-url-zai.md b/changelog.d/fixes/7022-opencode-go-quota-url-zai.md deleted file mode 100644 index e136c66551..0000000000 --- a/changelog.d/fixes/7022-opencode-go-quota-url-zai.md +++ /dev/null @@ -1 +0,0 @@ -- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) diff --git a/changelog.d/fixes/7032-auggie-model-ids-v032.md b/changelog.d/fixes/7032-auggie-model-ids-v032.md deleted file mode 100644 index bec9929b7b..0000000000 --- a/changelog.d/fixes/7032-auggie-model-ids-v032.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). diff --git a/changelog.d/fixes/7033-dashboard-typecheck-gate.md b/changelog.d/fixes/7033-dashboard-typecheck-gate.md deleted file mode 100644 index 89a33f44d6..0000000000 --- a/changelog.d/fixes/7033-dashboard-typecheck-gate.md +++ /dev/null @@ -1 +0,0 @@ -- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) diff --git a/changelog.d/fixes/7049-dashboard-port-env-fallback.md b/changelog.d/fixes/7049-dashboard-port-env-fallback.md deleted file mode 100644 index b3c51761ea..0000000000 --- a/changelog.d/fixes/7049-dashboard-port-env-fallback.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). diff --git a/changelog.d/fixes/7051-turbopack-compression-ignoreissue.md b/changelog.d/fixes/7051-turbopack-compression-ignoreissue.md deleted file mode 100644 index 017b5b8c78..0000000000 --- a/changelog.d/fixes/7051-turbopack-compression-ignoreissue.md +++ /dev/null @@ -1 +0,0 @@ -- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) diff --git a/changelog.d/fixes/7058-zai-web-proxy-connection-test.md b/changelog.d/fixes/7058-zai-web-proxy-connection-test.md deleted file mode 100644 index f7d453d734..0000000000 --- a/changelog.d/fixes/7058-zai-web-proxy-connection-test.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) diff --git a/changelog.d/fixes/7071-ollama-cloud-session-quota.md b/changelog.d/fixes/7071-ollama-cloud-session-quota.md deleted file mode 100644 index 81807e30ad..0000000000 --- a/changelog.d/fixes/7071-ollama-cloud-session-quota.md +++ /dev/null @@ -1 +0,0 @@ -- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) diff --git a/changelog.d/fixes/7072-quota-card-grid-mobile.md b/changelog.d/fixes/7072-quota-card-grid-mobile.md deleted file mode 100644 index df74be8a75..0000000000 --- a/changelog.d/fixes/7072-quota-card-grid-mobile.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) diff --git a/changelog.d/fixes/7080-proxy-test-connection-saved-proxyid.md b/changelog.d/fixes/7080-proxy-test-connection-saved-proxyid.md deleted file mode 100644 index cc374b6a8a..0000000000 --- a/changelog.d/fixes/7080-proxy-test-connection-saved-proxyid.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) diff --git a/changelog.d/fixes/7098-mimo-thinking-model-reasoning-content.md b/changelog.d/fixes/7098-mimo-thinking-model-reasoning-content.md deleted file mode 100644 index ddd454f252..0000000000 --- a/changelog.d/fixes/7098-mimo-thinking-model-reasoning-content.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z diff --git a/changelog.d/fixes/7125-onboarding-tiers-layout.md b/changelog.d/fixes/7125-onboarding-tiers-layout.md deleted file mode 100644 index 8bb9f718eb..0000000000 --- a/changelog.d/fixes/7125-onboarding-tiers-layout.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias diff --git a/changelog.d/fixes/7134-claude-web-400-no-response-body.md b/changelog.d/fixes/7134-claude-web-400-no-response-body.md deleted file mode 100644 index f9fd94cf5f..0000000000 --- a/changelog.d/fixes/7134-claude-web-400-no-response-body.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). diff --git a/changelog.d/fixes/7149-combo-scope-proxy-dead.md b/changelog.d/fixes/7149-combo-scope-proxy-dead.md deleted file mode 100644 index fcbbccb065..0000000000 --- a/changelog.d/fixes/7149-combo-scope-proxy-dead.md +++ /dev/null @@ -1 +0,0 @@ -- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) diff --git a/changelog.d/fixes/7151-hermes-agent-model-aliases.md b/changelog.d/fixes/7151-hermes-agent-model-aliases.md deleted file mode 100644 index b408b03462..0000000000 --- a/changelog.d/fixes/7151-hermes-agent-model-aliases.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) diff --git a/changelog.d/fixes/7156-legacy-model-picker-hidden-filter.md b/changelog.d/fixes/7156-legacy-model-picker-hidden-filter.md deleted file mode 100644 index cb3edb1642..0000000000 --- a/changelog.d/fixes/7156-legacy-model-picker-hidden-filter.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) diff --git a/changelog.d/fixes/7157-agent-bridge-dns-405.md b/changelog.d/fixes/7157-agent-bridge-dns-405.md deleted file mode 100644 index 98a887ce2a..0000000000 --- a/changelog.d/fixes/7157-agent-bridge-dns-405.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) diff --git a/changelog.d/fixes/7161-free-pool-handletogglesource.md b/changelog.d/fixes/7161-free-pool-handletogglesource.md deleted file mode 100644 index b85d16d651..0000000000 --- a/changelog.d/fixes/7161-free-pool-handletogglesource.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) diff --git a/changelog.d/fixes/7163-gemini-web-duplicated-text.md b/changelog.d/fixes/7163-gemini-web-duplicated-text.md deleted file mode 100644 index 6bac17d7e8..0000000000 --- a/changelog.d/fixes/7163-gemini-web-duplicated-text.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) diff --git a/changelog.d/fixes/7171-codex-responses-lite-parallel-tools.md b/changelog.d/fixes/7171-codex-responses-lite-parallel-tools.md deleted file mode 100644 index 328f60441a..0000000000 --- a/changelog.d/fixes/7171-codex-responses-lite-parallel-tools.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 diff --git a/changelog.d/fixes/7206-preserve-reasoning-openai-bridge.md b/changelog.d/fixes/7206-preserve-reasoning-openai-bridge.md deleted file mode 100644 index 449071b4c0..0000000000 --- a/changelog.d/fixes/7206-preserve-reasoning-openai-bridge.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) diff --git a/changelog.d/fixes/7207-openai-projection-gemini-clients.md b/changelog.d/fixes/7207-openai-projection-gemini-clients.md deleted file mode 100644 index 469549c0cc..0000000000 --- a/changelog.d/fixes/7207-openai-projection-gemini-clients.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) diff --git a/changelog.d/fixes/7208-cli-version-fastpath.md b/changelog.d/fixes/7208-cli-version-fastpath.md deleted file mode 100644 index 8635400667..0000000000 --- a/changelog.d/fixes/7208-cli-version-fastpath.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) diff --git a/changelog.d/fixes/7226-dast-smoke-backend-only.md b/changelog.d/fixes/7226-dast-smoke-backend-only.md deleted file mode 100644 index 63d2ae9ef0..0000000000 --- a/changelog.d/fixes/7226-dast-smoke-backend-only.md +++ /dev/null @@ -1 +0,0 @@ -- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) diff --git a/changelog.d/fixes/7234-bulk-add-keys-no-overwrite.md b/changelog.d/fixes/7234-bulk-add-keys-no-overwrite.md deleted file mode 100644 index 853a1103d2..0000000000 --- a/changelog.d/fixes/7234-bulk-add-keys-no-overwrite.md +++ /dev/null @@ -1 +0,0 @@ -- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) diff --git a/changelog.d/fixes/7237-vision-compression-authoritative-capability.md b/changelog.d/fixes/7237-vision-compression-authoritative-capability.md deleted file mode 100644 index 8fa0b61e3e..0000000000 --- a/changelog.d/fixes/7237-vision-compression-authoritative-capability.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) diff --git a/changelog.d/fixes/7242-openai-gpt56-responses-routing.md b/changelog.d/fixes/7242-openai-gpt56-responses-routing.md deleted file mode 100644 index 9b4141b817..0000000000 --- a/changelog.d/fixes/7242-openai-gpt56-responses-routing.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) diff --git a/changelog.d/fixes/7244-grok-cli-honor-proxy.md b/changelog.d/fixes/7244-grok-cli-honor-proxy.md deleted file mode 100644 index 6a83400d73..0000000000 --- a/changelog.d/fixes/7244-grok-cli-honor-proxy.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) diff --git a/changelog.d/fixes/7247-nvidia-nim-catalog.md b/changelog.d/fixes/7247-nvidia-nim-catalog.md deleted file mode 100644 index 9584dcbd97..0000000000 --- a/changelog.d/fixes/7247-nvidia-nim-catalog.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) diff --git a/changelog.d/fixes/7248-claude-bypass-content-reconstruction.md b/changelog.d/fixes/7248-claude-bypass-content-reconstruction.md deleted file mode 100644 index f55c03398d..0000000000 --- a/changelog.d/fixes/7248-claude-bypass-content-reconstruction.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) diff --git a/changelog.d/fixes/7249-windows-build-isolation.md b/changelog.d/fixes/7249-windows-build-isolation.md deleted file mode 100644 index 1c2997dc2c..0000000000 --- a/changelog.d/fixes/7249-windows-build-isolation.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) diff --git a/changelog.d/fixes/7250-provider-model-filter-live-catalog.md b/changelog.d/fixes/7250-provider-model-filter-live-catalog.md deleted file mode 100644 index b8b3c72266..0000000000 --- a/changelog.d/fixes/7250-provider-model-filter-live-catalog.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) diff --git a/changelog.d/fixes/7253-release-green-drift.md b/changelog.d/fixes/7253-release-green-drift.md deleted file mode 100644 index 3ab36730a8..0000000000 --- a/changelog.d/fixes/7253-release-green-drift.md +++ /dev/null @@ -1 +0,0 @@ -- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) diff --git a/changelog.d/fixes/7255-nonstreaming-gemini-family-projection.md b/changelog.d/fixes/7255-nonstreaming-gemini-family-projection.md deleted file mode 100644 index 8e0ce75dc1..0000000000 --- a/changelog.d/fixes/7255-nonstreaming-gemini-family-projection.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) diff --git a/changelog.d/fixes/7258-zhtw-missing-placeholder.md b/changelog.d/fixes/7258-zhtw-missing-placeholder.md deleted file mode 100644 index f3b85c0e00..0000000000 --- a/changelog.d/fixes/7258-zhtw-missing-placeholder.md +++ /dev/null @@ -1 +0,0 @@ -- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) diff --git a/changelog.d/fixes/7263-settings-local-only.md b/changelog.d/fixes/7263-settings-local-only.md deleted file mode 100644 index b32a211449..0000000000 --- a/changelog.d/fixes/7263-settings-local-only.md +++ /dev/null @@ -1 +0,0 @@ -- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) diff --git a/changelog.d/fixes/7265-termux-playwright-static-import.md b/changelog.d/fixes/7265-termux-playwright-static-import.md deleted file mode 100644 index 93eaf69a0a..0000000000 --- a/changelog.d/fixes/7265-termux-playwright-static-import.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) diff --git a/changelog.d/fixes/7266-proxyfetch-caller-abort-log.md b/changelog.d/fixes/7266-proxyfetch-caller-abort-log.md deleted file mode 100644 index a84b4b9d9b..0000000000 --- a/changelog.d/fixes/7266-proxyfetch-caller-abort-log.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) diff --git a/changelog.d/fixes/7268-model-not-supported-401-lockout.md b/changelog.d/fixes/7268-model-not-supported-401-lockout.md deleted file mode 100644 index d4ae8888b9..0000000000 --- a/changelog.d/fixes/7268-model-not-supported-401-lockout.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) diff --git a/changelog.d/fixes/7272-costs-page-500.md b/changelog.d/fixes/7272-costs-page-500.md deleted file mode 100644 index f342749da0..0000000000 --- a/changelog.d/fixes/7272-costs-page-500.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) diff --git a/changelog.d/fixes/7275-windows-cert-check-uninstall-hardcoded-legacy-host.md b/changelog.d/fixes/7275-windows-cert-check-uninstall-hardcoded-legacy-host.md deleted file mode 100644 index 47644a3181..0000000000 --- a/changelog.d/fixes/7275-windows-cert-check-uninstall-hardcoded-legacy-host.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) diff --git a/changelog.d/fixes/7279-cli-detector-windows-drift.md b/changelog.d/fixes/7279-cli-detector-windows-drift.md deleted file mode 100644 index e6a8fd53df..0000000000 --- a/changelog.d/fixes/7279-cli-detector-windows-drift.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) diff --git a/changelog.d/fixes/7284-conn-test-429.md b/changelog.d/fixes/7284-conn-test-429.md deleted file mode 100644 index fe4af30c12..0000000000 --- a/changelog.d/fixes/7284-conn-test-429.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) diff --git a/changelog.d/fixes/7285-combo-finish-reason.md b/changelog.d/fixes/7285-combo-finish-reason.md deleted file mode 100644 index 71515e48ca..0000000000 --- a/changelog.d/fixes/7285-combo-finish-reason.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) diff --git a/changelog.d/fixes/7288-sqljs-preinit-ordering-gap.md b/changelog.d/fixes/7288-sqljs-preinit-ordering-gap.md deleted file mode 100644 index 07acc66712..0000000000 --- a/changelog.d/fixes/7288-sqljs-preinit-ordering-gap.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) diff --git a/changelog.d/fixes/7289-cursor-effort-suffix.md b/changelog.d/fixes/7289-cursor-effort-suffix.md deleted file mode 100644 index 27905a5534..0000000000 --- a/changelog.d/fixes/7289-cursor-effort-suffix.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) diff --git a/changelog.d/fixes/7293-strict-system-message-hoist.md b/changelog.d/fixes/7293-strict-system-message-hoist.md deleted file mode 100644 index f79efd1f8a..0000000000 --- a/changelog.d/fixes/7293-strict-system-message-hoist.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) diff --git a/changelog.d/fixes/7297-bedrock-images.md b/changelog.d/fixes/7297-bedrock-images.md deleted file mode 100644 index 4d64923517..0000000000 --- a/changelog.d/fixes/7297-bedrock-images.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) diff --git a/changelog.d/fixes/7302-cli-electron-env.md b/changelog.d/fixes/7302-cli-electron-env.md deleted file mode 100644 index 63fbe89477..0000000000 --- a/changelog.d/fixes/7302-cli-electron-env.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) diff --git a/changelog.d/fixes/7350-rerank-proxy-pinning.md b/changelog.d/fixes/7350-rerank-proxy-pinning.md deleted file mode 100644 index 29bd56856b..0000000000 --- a/changelog.d/fixes/7350-rerank-proxy-pinning.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry diff --git a/changelog.d/fixes/7353-electron-hashed-externals.md b/changelog.d/fixes/7353-electron-hashed-externals.md deleted file mode 100644 index 98cb215092..0000000000 --- a/changelog.d/fixes/7353-electron-hashed-externals.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking diff --git a/changelog.d/fixes/7357-chatgpt-web-async-image-messages-array.md b/changelog.d/fixes/7357-chatgpt-web-async-image-messages-array.md deleted file mode 100644 index 45ae02efc8..0000000000 --- a/changelog.d/fixes/7357-chatgpt-web-async-image-messages-array.md +++ /dev/null @@ -1 +0,0 @@ -- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) diff --git a/changelog.d/fixes/7364-glm-4.6v-max-tokens-clamp.md b/changelog.d/fixes/7364-glm-4.6v-max-tokens-clamp.md deleted file mode 100644 index c4ce943d91..0000000000 --- a/changelog.d/fixes/7364-glm-4.6v-max-tokens-clamp.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) diff --git a/changelog.d/fixes/7364-zai-glm-target-format.md b/changelog.d/fixes/7364-zai-glm-target-format.md deleted file mode 100644 index a2f6fef807..0000000000 --- a/changelog.d/fixes/7364-zai-glm-target-format.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) diff --git a/changelog.d/fixes/7387-sticky-quota-exhausted.md b/changelog.d/fixes/7387-sticky-quota-exhausted.md deleted file mode 100644 index 1273c78a37..0000000000 --- a/changelog.d/fixes/7387-sticky-quota-exhausted.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) diff --git a/changelog.d/fixes/7388-codex-ws-history-per-turn.md b/changelog.d/fixes/7388-codex-ws-history-per-turn.md deleted file mode 100644 index 2e6e23a280..0000000000 --- a/changelog.d/fixes/7388-codex-ws-history-per-turn.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) diff --git a/changelog.d/fixes/7425-voyage-embedding-models.md b/changelog.d/fixes/7425-voyage-embedding-models.md deleted file mode 100644 index 3ac41f57eb..0000000000 --- a/changelog.d/fixes/7425-voyage-embedding-models.md +++ /dev/null @@ -1 +0,0 @@ -- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) diff --git a/changelog.d/fixes/7447-kimi-cn-key-format.md b/changelog.d/fixes/7447-kimi-cn-key-format.md deleted file mode 100644 index 9bd45b2eb2..0000000000 --- a/changelog.d/fixes/7447-kimi-cn-key-format.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) diff --git a/changelog.d/fixes/7490-align-engines-node.md b/changelog.d/fixes/7490-align-engines-node.md deleted file mode 100644 index 2b6839f774..0000000000 --- a/changelog.d/fixes/7490-align-engines-node.md +++ /dev/null @@ -1 +0,0 @@ -- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) diff --git a/changelog.d/fixes/7493-vietnamese-locale-quality.md b/changelog.d/fixes/7493-vietnamese-locale-quality.md deleted file mode 100644 index 984f08c9e6..0000000000 --- a/changelog.d/fixes/7493-vietnamese-locale-quality.md +++ /dev/null @@ -1 +0,0 @@ -- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) diff --git a/changelog.d/fixes/7494-sqljs-close-poison.md b/changelog.d/fixes/7494-sqljs-close-poison.md deleted file mode 100644 index b6e97b5d6b..0000000000 --- a/changelog.d/fixes/7494-sqljs-close-poison.md +++ /dev/null @@ -1 +0,0 @@ -- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) diff --git a/changelog.d/fixes/7503-empty-choices-stream-readiness.md b/changelog.d/fixes/7503-empty-choices-stream-readiness.md deleted file mode 100644 index 95861c9e07..0000000000 --- a/changelog.d/fixes/7503-empty-choices-stream-readiness.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) diff --git a/changelog.d/fixes/7521-codex-test-probe-model.md b/changelog.d/fixes/7521-codex-test-probe-model.md deleted file mode 100644 index 8af6bbf9b6..0000000000 --- a/changelog.d/fixes/7521-codex-test-probe-model.md +++ /dev/null @@ -1 +0,0 @@ -- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). diff --git a/changelog.d/fixes/7522-codex-import-validate-refresh.md b/changelog.d/fixes/7522-codex-import-validate-refresh.md deleted file mode 100644 index 73ae7b0f20..0000000000 --- a/changelog.d/fixes/7522-codex-import-validate-refresh.md +++ /dev/null @@ -1 +0,0 @@ -- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). diff --git a/changelog.d/fixes/7523-codex-oauth-remote-host.md b/changelog.d/fixes/7523-codex-oauth-remote-host.md deleted file mode 100644 index f74a47b464..0000000000 --- a/changelog.d/fixes/7523-codex-oauth-remote-host.md +++ /dev/null @@ -1 +0,0 @@ -- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). diff --git a/changelog.d/fixes/7529-search-static-catalog.md b/changelog.d/fixes/7529-search-static-catalog.md deleted file mode 100644 index 3387691b81..0000000000 --- a/changelog.d/fixes/7529-search-static-catalog.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) diff --git a/changelog.d/fixes/7532-tool-search-responses-to-chat.md b/changelog.d/fixes/7532-tool-search-responses-to-chat.md deleted file mode 100644 index 28b0466b4f..0000000000 --- a/changelog.d/fixes/7532-tool-search-responses-to-chat.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) diff --git a/changelog.d/fixes/7533-verbosity-prompt-cache-key-leak.md b/changelog.d/fixes/7533-verbosity-prompt-cache-key-leak.md deleted file mode 100644 index 7fd90f93f1..0000000000 --- a/changelog.d/fixes/7533-verbosity-prompt-cache-key-leak.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) diff --git a/changelog.d/fixes/7534-usage-provider-display-name.md b/changelog.d/fixes/7534-usage-provider-display-name.md deleted file mode 100644 index 2354f914cf..0000000000 --- a/changelog.d/fixes/7534-usage-provider-display-name.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) diff --git a/changelog.d/fixes/7535-usage-model-dedup-normalized-key.md b/changelog.d/fixes/7535-usage-model-dedup-normalized-key.md deleted file mode 100644 index 77f6dd7ea7..0000000000 --- a/changelog.d/fixes/7535-usage-model-dedup-normalized-key.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) diff --git a/changelog.d/fixes/7536-codex-nonstream-peek-body-double-read.md b/changelog.d/fixes/7536-codex-nonstream-peek-body-double-read.md deleted file mode 100644 index 9f156104fe..0000000000 --- a/changelog.d/fixes/7536-codex-nonstream-peek-body-double-read.md +++ /dev/null @@ -1 +0,0 @@ -- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) diff --git a/changelog.d/fixes/7540-custom-tool-output-images.md b/changelog.d/fixes/7540-custom-tool-output-images.md deleted file mode 100644 index c22b4970a9..0000000000 --- a/changelog.d/fixes/7540-custom-tool-output-images.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue diff --git a/changelog.d/fixes/7542-arena-cookie-redirect.md b/changelog.d/fixes/7542-arena-cookie-redirect.md deleted file mode 100644 index 02513f6a50..0000000000 --- a/changelog.d/fixes/7542-arena-cookie-redirect.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) diff --git a/changelog.d/fixes/7545-combo-failover-truncated-sse.md b/changelog.d/fixes/7545-combo-failover-truncated-sse.md deleted file mode 100644 index 1f0c9852c8..0000000000 --- a/changelog.d/fixes/7545-combo-failover-truncated-sse.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 diff --git a/changelog.d/fixes/7547-prefer-public-endpoint-url.md b/changelog.d/fixes/7547-prefer-public-endpoint-url.md deleted file mode 100644 index 387f0d09a1..0000000000 --- a/changelog.d/fixes/7547-prefer-public-endpoint-url.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 diff --git a/changelog.d/fixes/7548-claude-web-ua.md b/changelog.d/fixes/7548-claude-web-ua.md deleted file mode 100644 index c5f2d5f623..0000000000 --- a/changelog.d/fixes/7548-claude-web-ua.md +++ /dev/null @@ -1 +0,0 @@ -- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) diff --git a/changelog.d/fixes/7586-windows-sqlite-launch.md b/changelog.d/fixes/7586-windows-sqlite-launch.md deleted file mode 100644 index 735f7b7556..0000000000 --- a/changelog.d/fixes/7586-windows-sqlite-launch.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) diff --git a/changelog.d/fixes/7587-vscode-models-missing-openai.md b/changelog.d/fixes/7587-vscode-models-missing-openai.md deleted file mode 100644 index c5fd715438..0000000000 --- a/changelog.d/fixes/7587-vscode-models-missing-openai.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) diff --git a/changelog.d/fixes/7610-grok-cli-auth-json-paste.md b/changelog.d/fixes/7610-grok-cli-auth-json-paste.md deleted file mode 100644 index dc42068466..0000000000 --- a/changelog.d/fixes/7610-grok-cli-auth-json-paste.md +++ /dev/null @@ -1 +0,0 @@ -- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). diff --git a/changelog.d/fixes/7610-grok-proactive-refresh.md b/changelog.d/fixes/7610-grok-proactive-refresh.md deleted file mode 100644 index c6525e0aeb..0000000000 --- a/changelog.d/fixes/7610-grok-proactive-refresh.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) diff --git a/changelog.d/fixes/7611-grok-cli-function-call-output-sanitize.md b/changelog.d/fixes/7611-grok-cli-function-call-output-sanitize.md deleted file mode 100644 index f078f38633..0000000000 --- a/changelog.d/fixes/7611-grok-cli-function-call-output-sanitize.md +++ /dev/null @@ -1 +0,0 @@ -- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). diff --git a/changelog.d/fixes/7613-responses-completed-guard-seen-call-ids.md b/changelog.d/fixes/7613-responses-completed-guard-seen-call-ids.md deleted file mode 100644 index b2e32f26be..0000000000 --- a/changelog.d/fixes/7613-responses-completed-guard-seen-call-ids.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers diff --git a/changelog.d/fixes/7617-nvidia-strip-cache-key.md b/changelog.d/fixes/7617-nvidia-strip-cache-key.md deleted file mode 100644 index d3909c9256..0000000000 --- a/changelog.d/fixes/7617-nvidia-strip-cache-key.md +++ /dev/null @@ -1 +0,0 @@ -- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) diff --git a/changelog.d/fixes/7620-noauth-hidden-filter.md b/changelog.d/fixes/7620-noauth-hidden-filter.md deleted file mode 100644 index 0c106c6931..0000000000 --- a/changelog.d/fixes/7620-noauth-hidden-filter.md +++ /dev/null @@ -1 +0,0 @@ -- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) diff --git a/changelog.d/fixes/7621-chutes-baseurl.md b/changelog.d/fixes/7621-chutes-baseurl.md deleted file mode 100644 index 98683834fc..0000000000 --- a/changelog.d/fixes/7621-chutes-baseurl.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) diff --git a/changelog.d/fixes/7629-provider-flow-consistency.md b/changelog.d/fixes/7629-provider-flow-consistency.md deleted file mode 100644 index abe3f24845..0000000000 --- a/changelog.d/fixes/7629-provider-flow-consistency.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) diff --git a/changelog.d/fixes/7638-mistral-401-classify.md b/changelog.d/fixes/7638-mistral-401-classify.md deleted file mode 100644 index a725fc6bbf..0000000000 --- a/changelog.d/fixes/7638-mistral-401-classify.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) diff --git a/changelog.d/fixes/7645-cliproxyapi-credential.md b/changelog.d/fixes/7645-cliproxyapi-credential.md deleted file mode 100644 index ec1ad8ecfa..0000000000 --- a/changelog.d/fixes/7645-cliproxyapi-credential.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) diff --git a/changelog.d/fixes/7661-fumadocs-devdep.md b/changelog.d/fixes/7661-fumadocs-devdep.md deleted file mode 100644 index 7340d36184..0000000000 --- a/changelog.d/fixes/7661-fumadocs-devdep.md +++ /dev/null @@ -1 +0,0 @@ -- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) diff --git a/changelog.d/fixes/7662-combos-auto-enumerate-all-variants.md b/changelog.d/fixes/7662-combos-auto-enumerate-all-variants.md deleted file mode 100644 index 8bfb299c77..0000000000 --- a/changelog.d/fixes/7662-combos-auto-enumerate-all-variants.md +++ /dev/null @@ -1 +0,0 @@ -- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. diff --git a/changelog.d/fixes/7676-gemini-persist-cookies.md b/changelog.d/fixes/7676-gemini-persist-cookies.md deleted file mode 100644 index 9e320d7ef1..0000000000 --- a/changelog.d/fixes/7676-gemini-persist-cookies.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) diff --git a/changelog.d/fixes/7680-rtl-physical-utilities.md b/changelog.d/fixes/7680-rtl-physical-utilities.md deleted file mode 100644 index 7da1eb4779..0000000000 --- a/changelog.d/fixes/7680-rtl-physical-utilities.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) diff --git a/changelog.d/fixes/7682-opencode-shared-alias.md b/changelog.d/fixes/7682-opencode-shared-alias.md deleted file mode 100644 index 61d486efe5..0000000000 --- a/changelog.d/fixes/7682-opencode-shared-alias.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) diff --git a/changelog.d/fixes/7693-wildcard-alias.md b/changelog.d/fixes/7693-wildcard-alias.md deleted file mode 100644 index e921dca52e..0000000000 --- a/changelog.d/fixes/7693-wildcard-alias.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) diff --git a/changelog.d/fixes/7701-mcp-undici-copy.md b/changelog.d/fixes/7701-mcp-undici-copy.md deleted file mode 100644 index 0d05d9cf96..0000000000 --- a/changelog.d/fixes/7701-mcp-undici-copy.md +++ /dev/null @@ -1 +0,0 @@ -- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) diff --git a/changelog.d/fixes/7705-claude-tool-result-id.md b/changelog.d/fixes/7705-claude-tool-result-id.md deleted file mode 100644 index e3f1503b49..0000000000 --- a/changelog.d/fixes/7705-claude-tool-result-id.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) diff --git a/changelog.d/fixes/7707-proxy-password-rotation.md b/changelog.d/fixes/7707-proxy-password-rotation.md deleted file mode 100644 index 21297b5eeb..0000000000 --- a/changelog.d/fixes/7707-proxy-password-rotation.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius diff --git a/changelog.d/fixes/7737-codex-multiaccount.md b/changelog.d/fixes/7737-codex-multiaccount.md deleted file mode 100644 index 51ae1ad207..0000000000 --- a/changelog.d/fixes/7737-codex-multiaccount.md +++ /dev/null @@ -1 +0,0 @@ -- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) diff --git a/changelog.d/fixes/7740-phantom-health-popup.md b/changelog.d/fixes/7740-phantom-health-popup.md deleted file mode 100644 index 8315f54856..0000000000 --- a/changelog.d/fixes/7740-phantom-health-popup.md +++ /dev/null @@ -1 +0,0 @@ -- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) diff --git a/changelog.d/fixes/7744-cache-provider-connections-by-id-nodes.md b/changelog.d/fixes/7744-cache-provider-connections-by-id-nodes.md deleted file mode 100644 index fc3ad8fc5a..0000000000 --- a/changelog.d/fixes/7744-cache-provider-connections-by-id-nodes.md +++ /dev/null @@ -1 +0,0 @@ -- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) diff --git a/changelog.d/fixes/7746-ccr-prompt-marker-loss.md b/changelog.d/fixes/7746-ccr-prompt-marker-loss.md deleted file mode 100644 index 9e13f165ca..0000000000 --- a/changelog.d/fixes/7746-ccr-prompt-marker-loss.md +++ /dev/null @@ -1 +0,0 @@ -- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) diff --git a/changelog.d/fixes/7752-antigravity-orphan-tooluse.md b/changelog.d/fixes/7752-antigravity-orphan-tooluse.md deleted file mode 100644 index 432c88f1c9..0000000000 --- a/changelog.d/fixes/7752-antigravity-orphan-tooluse.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) diff --git a/changelog.d/fixes/7753-windows-cli-path.md b/changelog.d/fixes/7753-windows-cli-path.md deleted file mode 100644 index f75dfd6d03..0000000000 --- a/changelog.d/fixes/7753-windows-cli-path.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) diff --git a/changelog.d/fixes/7764-quota-card-order.md b/changelog.d/fixes/7764-quota-card-order.md deleted file mode 100644 index c2579c3eb7..0000000000 --- a/changelog.d/fixes/7764-quota-card-order.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) diff --git a/changelog.d/fixes/7773-termux-sqlite-boot.md b/changelog.d/fixes/7773-termux-sqlite-boot.md deleted file mode 100644 index 52759ed194..0000000000 --- a/changelog.d/fixes/7773-termux-sqlite-boot.md +++ /dev/null @@ -1 +0,0 @@ -- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) diff --git a/changelog.d/fixes/7777-cc-bridge-openai-image-blocks.md b/changelog.d/fixes/7777-cc-bridge-openai-image-blocks.md deleted file mode 100644 index 619cf10692..0000000000 --- a/changelog.d/fixes/7777-cc-bridge-openai-image-blocks.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) diff --git a/changelog.d/fixes/7787-provider-connections-raw-cache-lazy-decrypt.md b/changelog.d/fixes/7787-provider-connections-raw-cache-lazy-decrypt.md deleted file mode 100644 index 1dc802f929..0000000000 --- a/changelog.d/fixes/7787-provider-connections-raw-cache-lazy-decrypt.md +++ /dev/null @@ -1 +0,0 @@ -- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) diff --git a/changelog.d/fixes/7793-env-doc-sync-redaction.md b/changelog.d/fixes/7793-env-doc-sync-redaction.md deleted file mode 100644 index 7f9d0979f5..0000000000 --- a/changelog.d/fixes/7793-env-doc-sync-redaction.md +++ /dev/null @@ -1 +0,0 @@ -- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) diff --git a/changelog.d/fixes/7794-pipeline-transient-retry.md b/changelog.d/fixes/7794-pipeline-transient-retry.md deleted file mode 100644 index aa6826ce6c..0000000000 --- a/changelog.d/fixes/7794-pipeline-transient-retry.md +++ /dev/null @@ -1 +0,0 @@ -- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) diff --git a/changelog.d/fixes/7802-tls-client-native-lib.md b/changelog.d/fixes/7802-tls-client-native-lib.md deleted file mode 100644 index c67d6078a9..0000000000 --- a/changelog.d/fixes/7802-tls-client-native-lib.md +++ /dev/null @@ -1 +0,0 @@ -- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) diff --git a/changelog.d/fixes/7812-release-regressions.md b/changelog.d/fixes/7812-release-regressions.md deleted file mode 100644 index 69befb0b9a..0000000000 --- a/changelog.d/fixes/7812-release-regressions.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). diff --git a/changelog.d/fixes/7814-antigravity-onboarding-empty-projectid.md b/changelog.d/fixes/7814-antigravity-onboarding-empty-projectid.md deleted file mode 100644 index b91fe2322d..0000000000 --- a/changelog.d/fixes/7814-antigravity-onboarding-empty-projectid.md +++ /dev/null @@ -1 +0,0 @@ -- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) diff --git a/changelog.d/fixes/7820-amazon-q-static-models.md b/changelog.d/fixes/7820-amazon-q-static-models.md deleted file mode 100644 index 00cfec68d7..0000000000 --- a/changelog.d/fixes/7820-amazon-q-static-models.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) diff --git a/changelog.d/fixes/7821-gpt56-codex-responses-lite.md b/changelog.d/fixes/7821-gpt56-codex-responses-lite.md deleted file mode 100644 index ca852493aa..0000000000 --- a/changelog.d/fixes/7821-gpt56-codex-responses-lite.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) diff --git a/changelog.d/fixes/7837-release-green-eslint-json.md b/changelog.d/fixes/7837-release-green-eslint-json.md deleted file mode 100644 index 77af4754ad..0000000000 --- a/changelog.d/fixes/7837-release-green-eslint-json.md +++ /dev/null @@ -1 +0,0 @@ -- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) diff --git a/changelog.d/fixes/7842-nightly-compat-node2426.md b/changelog.d/fixes/7842-nightly-compat-node2426.md deleted file mode 100644 index e34285d7e3..0000000000 --- a/changelog.d/fixes/7842-nightly-compat-node2426.md +++ /dev/null @@ -1 +0,0 @@ -- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) diff --git a/changelog.d/fixes/7844-dashboard-no-cmd-fallback.md b/changelog.d/fixes/7844-dashboard-no-cmd-fallback.md deleted file mode 100644 index 5f603edaa8..0000000000 --- a/changelog.d/fixes/7844-dashboard-no-cmd-fallback.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) diff --git a/changelog.d/fixes/7845-log-detail-structured-error.md b/changelog.d/fixes/7845-log-detail-structured-error.md deleted file mode 100644 index 909c9ff960..0000000000 --- a/changelog.d/fixes/7845-log-detail-structured-error.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) diff --git a/changelog.d/fixes/7847-bound-client-raw-request.md b/changelog.d/fixes/7847-bound-client-raw-request.md deleted file mode 100644 index 80ef4870d8..0000000000 --- a/changelog.d/fixes/7847-bound-client-raw-request.md +++ /dev/null @@ -1 +0,0 @@ -- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length diff --git a/changelog.d/fixes/7847-combo-attempt-body-cow.md b/changelog.d/fixes/7847-combo-attempt-body-cow.md deleted file mode 100644 index afa3539cd0..0000000000 --- a/changelog.d/fixes/7847-combo-attempt-body-cow.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next diff --git a/changelog.d/fixes/7847-structural-json-size.md b/changelog.d/fixes/7847-structural-json-size.md deleted file mode 100644 index 31bfe11f2e..0000000000 --- a/changelog.d/fixes/7847-structural-json-size.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured diff --git a/changelog.d/fixes/7856-copilot-reasoning-text.md b/changelog.d/fixes/7856-copilot-reasoning-text.md deleted file mode 100644 index 69ba5613fc..0000000000 --- a/changelog.d/fixes/7856-copilot-reasoning-text.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) diff --git a/changelog.d/fixes/7857-web-cookie-validation-probe.md b/changelog.d/fixes/7857-web-cookie-validation-probe.md deleted file mode 100644 index cb88be58f1..0000000000 --- a/changelog.d/fixes/7857-web-cookie-validation-probe.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) diff --git a/changelog.d/fixes/7858-copilot-m365-web-empty-frame.md b/changelog.d/fixes/7858-copilot-m365-web-empty-frame.md deleted file mode 100644 index d24c5d86f9..0000000000 --- a/changelog.d/fixes/7858-copilot-m365-web-empty-frame.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) diff --git a/changelog.d/fixes/7859-gemini-web-redirect.md b/changelog.d/fixes/7859-gemini-web-redirect.md deleted file mode 100644 index a6f8388826..0000000000 --- a/changelog.d/fixes/7859-gemini-web-redirect.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) diff --git a/changelog.d/fixes/7868-reset-password-sqlite-bindings.md b/changelog.d/fixes/7868-reset-password-sqlite-bindings.md deleted file mode 100644 index 63f6b31313..0000000000 --- a/changelog.d/fixes/7868-reset-password-sqlite-bindings.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) diff --git a/changelog.d/fixes/7875-healthcheck-jitter-config.md b/changelog.d/fixes/7875-healthcheck-jitter-config.md deleted file mode 100644 index 499820acef..0000000000 --- a/changelog.d/fixes/7875-healthcheck-jitter-config.md +++ /dev/null @@ -1 +0,0 @@ -- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) diff --git a/changelog.d/fixes/7884-opencode-management-read-token.md b/changelog.d/fixes/7884-opencode-management-read-token.md deleted file mode 100644 index 1ab12e0f29..0000000000 --- a/changelog.d/fixes/7884-opencode-management-read-token.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) diff --git a/changelog.d/fixes/7889-quota-cutoff-drafts.md b/changelog.d/fixes/7889-quota-cutoff-drafts.md deleted file mode 100644 index 177a1a37fc..0000000000 --- a/changelog.d/fixes/7889-quota-cutoff-drafts.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). diff --git a/changelog.d/fixes/7906-anthropic-thinking-signature-recovery.md b/changelog.d/fixes/7906-anthropic-thinking-signature-recovery.md deleted file mode 100644 index 48d291753b..0000000000 --- a/changelog.d/fixes/7906-anthropic-thinking-signature-recovery.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) diff --git a/changelog.d/fixes/7907-chatcore-499-string-abort.md b/changelog.d/fixes/7907-chatcore-499-string-abort.md deleted file mode 100644 index 0d3ef1e90c..0000000000 --- a/changelog.d/fixes/7907-chatcore-499-string-abort.md +++ /dev/null @@ -1 +0,0 @@ -- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. diff --git a/changelog.d/fixes/7907-ignore-client-abort-resilience.md b/changelog.d/fixes/7907-ignore-client-abort-resilience.md deleted file mode 100644 index 5998b774ea..0000000000 --- a/changelog.d/fixes/7907-ignore-client-abort-resilience.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) diff --git a/changelog.d/fixes/7913-opencode-spawnsync-einval-win32.md b/changelog.d/fixes/7913-opencode-spawnsync-einval-win32.md deleted file mode 100644 index 20d0c34b0b..0000000000 --- a/changelog.d/fixes/7913-opencode-spawnsync-einval-win32.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) diff --git a/changelog.d/fixes/7918-block-extra-usage-toggle-copy.md b/changelog.d/fixes/7918-block-extra-usage-toggle-copy.md deleted file mode 100644 index 9dadebf62b..0000000000 --- a/changelog.d/fixes/7918-block-extra-usage-toggle-copy.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) diff --git a/changelog.d/fixes/7925-windows-autostart-vbs.md b/changelog.d/fixes/7925-windows-autostart-vbs.md deleted file mode 100644 index f892a979c7..0000000000 --- a/changelog.d/fixes/7925-windows-autostart-vbs.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) diff --git a/changelog.d/fixes/7930-perplexity-web-quota-cooldown.md b/changelog.d/fixes/7930-perplexity-web-quota-cooldown.md deleted file mode 100644 index 948d880348..0000000000 --- a/changelog.d/fixes/7930-perplexity-web-quota-cooldown.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc diff --git a/changelog.d/fixes/7940-gemini-429-model-lockout.md b/changelog.d/fixes/7940-gemini-429-model-lockout.md deleted file mode 100644 index cac486caf9..0000000000 --- a/changelog.d/fixes/7940-gemini-429-model-lockout.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) diff --git a/changelog.d/fixes/7941-macos-dock-icon.md b/changelog.d/fixes/7941-macos-dock-icon.md deleted file mode 100644 index 91c66d41a9..0000000000 --- a/changelog.d/fixes/7941-macos-dock-icon.md +++ /dev/null @@ -1 +0,0 @@ -- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) diff --git a/changelog.d/fixes/7942-spark-openai-compatible-endpoint.md b/changelog.d/fixes/7942-spark-openai-compatible-endpoint.md deleted file mode 100644 index 09384e14a0..0000000000 --- a/changelog.d/fixes/7942-spark-openai-compatible-endpoint.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu diff --git a/changelog.d/fixes/7948-acp-agents-loopback-gate.md b/changelog.d/fixes/7948-acp-agents-loopback-gate.md deleted file mode 100644 index 5473138a2b..0000000000 --- a/changelog.d/fixes/7948-acp-agents-loopback-gate.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) diff --git a/changelog.d/fixes/7976-opencode-combo-double-prefix.md b/changelog.d/fixes/7976-opencode-combo-double-prefix.md deleted file mode 100644 index 36570e28a5..0000000000 --- a/changelog.d/fixes/7976-opencode-combo-double-prefix.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) diff --git a/changelog.d/fixes/7993-noauth-proxy-routing.md b/changelog.d/fixes/7993-noauth-proxy-routing.md deleted file mode 100644 index 3a929f87c6..0000000000 --- a/changelog.d/fixes/7993-noauth-proxy-routing.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): route noauth opencode-zen connections through their assigned proxy diff --git a/changelog.d/fixes/8000-duckduckgo-catalog.md b/changelog.d/fixes/8000-duckduckgo-catalog.md deleted file mode 100644 index 0eb43a4996..0000000000 --- a/changelog.d/fixes/8000-duckduckgo-catalog.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) diff --git a/changelog.d/fixes/8014-zai-web-auth.md b/changelog.d/fixes/8014-zai-web-auth.md deleted file mode 100644 index e836c3dacd..0000000000 --- a/changelog.d/fixes/8014-zai-web-auth.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) diff --git a/changelog.d/fixes/8020-codex-peek-read-timeout.md b/changelog.d/fixes/8020-codex-peek-read-timeout.md deleted file mode 100644 index a9b28e327c..0000000000 --- a/changelog.d/fixes/8020-codex-peek-read-timeout.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) diff --git a/changelog.d/fixes/8029-promptql-issuer-substring.md b/changelog.d/fixes/8029-promptql-issuer-substring.md deleted file mode 100644 index 9b523c0391..0000000000 --- a/changelog.d/fixes/8029-promptql-issuer-substring.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) diff --git a/changelog.d/fixes/8032-path-shaped-vision.md b/changelog.d/fixes/8032-path-shaped-vision.md deleted file mode 100644 index ce7cefa7d5..0000000000 --- a/changelog.d/fixes/8032-path-shaped-vision.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda diff --git a/changelog.d/fixes/8036-codex-cli-detect.md b/changelog.d/fixes/8036-codex-cli-detect.md deleted file mode 100644 index 467ecc0100..0000000000 --- a/changelog.d/fixes/8036-codex-cli-detect.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) diff --git a/changelog.d/fixes/8041-forwarded-response-header-budget.md b/changelog.d/fixes/8041-forwarded-response-header-budget.md deleted file mode 100644 index 39abd21147..0000000000 --- a/changelog.d/fixes/8041-forwarded-response-header-budget.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln diff --git a/changelog.d/fixes/8045-windows-wal-checkpoint.md b/changelog.d/fixes/8045-windows-wal-checkpoint.md deleted file mode 100644 index f76203b76f..0000000000 --- a/changelog.d/fixes/8045-windows-wal-checkpoint.md +++ /dev/null @@ -1 +0,0 @@ -- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) diff --git a/changelog.d/fixes/8046-codex-oauth-lan-ip.md b/changelog.d/fixes/8046-codex-oauth-lan-ip.md deleted file mode 100644 index e259c3ed6c..0000000000 --- a/changelog.d/fixes/8046-codex-oauth-lan-ip.md +++ /dev/null @@ -1 +0,0 @@ -- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) diff --git a/changelog.d/fixes/8052-codex-ws-compression.md b/changelog.d/fixes/8052-codex-ws-compression.md deleted file mode 100644 index 9a7a679d02..0000000000 --- a/changelog.d/fixes/8052-codex-ws-compression.md +++ /dev/null @@ -1,2 +0,0 @@ -- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) - diff --git a/changelog.d/fixes/8059-oauth-refresh-connection-dedup.md b/changelog.d/fixes/8059-oauth-refresh-connection-dedup.md deleted file mode 100644 index 29e077184e..0000000000 --- a/changelog.d/fixes/8059-oauth-refresh-connection-dedup.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) diff --git a/changelog.d/fixes/8065-quota-cache-globalthis.md b/changelog.d/fixes/8065-quota-cache-globalthis.md deleted file mode 100644 index 8c4251adc1..0000000000 --- a/changelog.d/fixes/8065-quota-cache-globalthis.md +++ /dev/null @@ -1 +0,0 @@ -- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) diff --git a/changelog.d/fixes/8082-poe-baseurl.md b/changelog.d/fixes/8082-poe-baseurl.md deleted file mode 100644 index c2627162d9..0000000000 --- a/changelog.d/fixes/8082-poe-baseurl.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) diff --git a/changelog.d/fixes/8083-responses-input-items-status.md b/changelog.d/fixes/8083-responses-input-items-status.md deleted file mode 100644 index d184d8dbee..0000000000 --- a/changelog.d/fixes/8083-responses-input-items-status.md +++ /dev/null @@ -1 +0,0 @@ -- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) diff --git a/changelog.d/fixes/8085-images-anon-fallback.md b/changelog.d/fixes/8085-images-anon-fallback.md deleted file mode 100644 index 77cd06e296..0000000000 --- a/changelog.d/fixes/8085-images-anon-fallback.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) diff --git a/changelog.d/fixes/8089-responses-system-image.md b/changelog.d/fixes/8089-responses-system-image.md deleted file mode 100644 index d372c97b89..0000000000 --- a/changelog.d/fixes/8089-responses-system-image.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) diff --git a/changelog.d/fixes/8091-supervisor-spawn-err.md b/changelog.d/fixes/8091-supervisor-spawn-err.md deleted file mode 100644 index 787321882e..0000000000 --- a/changelog.d/fixes/8091-supervisor-spawn-err.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) diff --git a/changelog.d/fixes/8098-antigravity-protocol-fidelity.md b/changelog.d/fixes/8098-antigravity-protocol-fidelity.md deleted file mode 100644 index 1c5b3974de..0000000000 --- a/changelog.d/fixes/8098-antigravity-protocol-fidelity.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 diff --git a/changelog.d/fixes/8107-resilience-cooldown-clamp.md b/changelog.d/fixes/8107-resilience-cooldown-clamp.md deleted file mode 100644 index 20d07160e5..0000000000 --- a/changelog.d/fixes/8107-resilience-cooldown-clamp.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) diff --git a/changelog.d/fixes/8134-github-t5-fallback-filter.md b/changelog.d/fixes/8134-github-t5-fallback-filter.md deleted file mode 100644 index cba43ee2a8..0000000000 --- a/changelog.d/fixes/8134-github-t5-fallback-filter.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) diff --git a/changelog.d/fixes/8136-antigravity-400-lockout.md b/changelog.d/fixes/8136-antigravity-400-lockout.md deleted file mode 100644 index 10de14be52..0000000000 --- a/changelog.d/fixes/8136-antigravity-400-lockout.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model diff --git a/changelog.d/fixes/8169-lite-word-boundary-truncation.md b/changelog.d/fixes/8169-lite-word-boundary-truncation.md deleted file mode 100644 index 4943d64cf0..0000000000 --- a/changelog.d/fixes/8169-lite-word-boundary-truncation.md +++ /dev/null @@ -1 +0,0 @@ -- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) diff --git a/changelog.d/fixes/8189-classifier-compat-auto-narrow.md b/changelog.d/fixes/8189-classifier-compat-auto-narrow.md deleted file mode 100644 index b23e509335..0000000000 --- a/changelog.d/fixes/8189-classifier-compat-auto-narrow.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) diff --git a/changelog.d/fixes/8200-perplexity-web-401-cooldown.md b/changelog.d/fixes/8200-perplexity-web-401-cooldown.md deleted file mode 100644 index 83742bdef3..0000000000 --- a/changelog.d/fixes/8200-perplexity-web-401-cooldown.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection diff --git a/changelog.d/fixes/8231-gemini-civic-integrity-default.md b/changelog.d/fixes/8231-gemini-civic-integrity-default.md deleted file mode 100644 index fc4159a0c0..0000000000 --- a/changelog.d/fixes/8231-gemini-civic-integrity-default.md +++ /dev/null @@ -1 +0,0 @@ -- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) diff --git a/changelog.d/fixes/8233-codex-dashboard-regressions.md b/changelog.d/fixes/8233-codex-dashboard-regressions.md deleted file mode 100644 index 831e86088f..0000000000 --- a/changelog.d/fixes/8233-codex-dashboard-regressions.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 diff --git a/changelog.d/fixes/8247-8248-accountfallback-model-unhealthy.md b/changelog.d/fixes/8247-8248-accountfallback-model-unhealthy.md deleted file mode 100644 index 42288526f4..0000000000 --- a/changelog.d/fixes/8247-8248-accountfallback-model-unhealthy.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) diff --git a/changelog.d/fixes/8250-kimi-k3-vision-capability.md b/changelog.d/fixes/8250-kimi-k3-vision-capability.md deleted file mode 100644 index af34851725..0000000000 --- a/changelog.d/fixes/8250-kimi-k3-vision-capability.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda diff --git a/changelog.d/fixes/8284-provider-docs-link.md b/changelog.d/fixes/8284-provider-docs-link.md deleted file mode 100644 index 771bf7c262..0000000000 --- a/changelog.d/fixes/8284-provider-docs-link.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu diff --git a/changelog.d/fixes/8295-namespace-leaf-collision.md b/changelog.d/fixes/8295-namespace-leaf-collision.md deleted file mode 100644 index 4cccd343fa..0000000000 --- a/changelog.d/fixes/8295-namespace-leaf-collision.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide diff --git a/changelog.d/fixes/8298-focused-8177-runtime-fixes.md b/changelog.d/fixes/8298-focused-8177-runtime-fixes.md deleted file mode 100644 index b688c1632b..0000000000 --- a/changelog.d/fixes/8298-focused-8177-runtime-fixes.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun diff --git a/changelog.d/fixes/8310-combo-responses-payload.md b/changelog.d/fixes/8310-combo-responses-payload.md deleted file mode 100644 index 631b1043d8..0000000000 --- a/changelog.d/fixes/8310-combo-responses-payload.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 diff --git a/changelog.d/fixes/8326-compatible-id-regex.md b/changelog.d/fixes/8326-compatible-id-regex.md deleted file mode 100644 index a637f4cef5..0000000000 --- a/changelog.d/fixes/8326-compatible-id-regex.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) diff --git a/changelog.d/fixes/8327-models-owned-by-prefix.md b/changelog.d/fixes/8327-models-owned-by-prefix.md deleted file mode 100644 index 4e23834052..0000000000 --- a/changelog.d/fixes/8327-models-owned-by-prefix.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) diff --git a/changelog.d/fixes/8328-topology-custom-providers.md b/changelog.d/fixes/8328-topology-custom-providers.md deleted file mode 100644 index b8fe294b24..0000000000 --- a/changelog.d/fixes/8328-topology-custom-providers.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) diff --git a/changelog.d/fixes/8331-usage-buffer-inflation.md b/changelog.d/fixes/8331-usage-buffer-inflation.md deleted file mode 100644 index 1ea77942a4..0000000000 --- a/changelog.d/fixes/8331-usage-buffer-inflation.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) diff --git a/changelog.d/fixes/8332-combo-vision-fallback.md b/changelog.d/fixes/8332-combo-vision-fallback.md deleted file mode 100644 index 40f784c397..0000000000 --- a/changelog.d/fixes/8332-combo-vision-fallback.md +++ /dev/null @@ -1 +0,0 @@ -- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) diff --git a/changelog.d/fixes/8350-hermes-oauth-usage-400.md b/changelog.d/fixes/8350-hermes-oauth-usage-400.md deleted file mode 100644 index 9dde1b4a4c..0000000000 --- a/changelog.d/fixes/8350-hermes-oauth-usage-400.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) diff --git a/changelog.d/fixes/8355-zhcn-zhtw-i18n-propernouns.md b/changelog.d/fixes/8355-zhcn-zhtw-i18n-propernouns.md deleted file mode 100644 index 6651a8f65a..0000000000 --- a/changelog.d/fixes/8355-zhcn-zhtw-i18n-propernouns.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). diff --git a/changelog.d/fixes/8368-image-token-context.md b/changelog.d/fixes/8368-image-token-context.md deleted file mode 100644 index b4641899da..0000000000 --- a/changelog.d/fixes/8368-image-token-context.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) diff --git a/changelog.d/fixes/8370-priority-affinity-reorder.md b/changelog.d/fixes/8370-priority-affinity-reorder.md deleted file mode 100644 index 851e000a82..0000000000 --- a/changelog.d/fixes/8370-priority-affinity-reorder.md +++ /dev/null @@ -1 +0,0 @@ -- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) diff --git a/changelog.d/fixes/8374-plugins-status-optional.md b/changelog.d/fixes/8374-plugins-status-optional.md deleted file mode 100644 index 2af60df3a0..0000000000 --- a/changelog.d/fixes/8374-plugins-status-optional.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) diff --git a/changelog.d/fixes/8376-econnrefused-breaker.md b/changelog.d/fixes/8376-econnrefused-breaker.md deleted file mode 100644 index 4e9756c203..0000000000 --- a/changelog.d/fixes/8376-econnrefused-breaker.md +++ /dev/null @@ -1 +0,0 @@ -- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) diff --git a/changelog.d/fixes/8385-perkey-proxy-global-toggle.md b/changelog.d/fixes/8385-perkey-proxy-global-toggle.md deleted file mode 100644 index f30d5a44ed..0000000000 --- a/changelog.d/fixes/8385-perkey-proxy-global-toggle.md +++ /dev/null @@ -1 +0,0 @@ -- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) diff --git a/changelog.d/fixes/8388-compression-detail-persist.md b/changelog.d/fixes/8388-compression-detail-persist.md deleted file mode 100644 index da963af987..0000000000 --- a/changelog.d/fixes/8388-compression-detail-persist.md +++ /dev/null @@ -1 +0,0 @@ -- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) diff --git a/changelog.d/fixes/8395-plugin-hooks-fire.md b/changelog.d/fixes/8395-plugin-hooks-fire.md deleted file mode 100644 index 4465f33254..0000000000 --- a/changelog.d/fixes/8395-plugin-hooks-fire.md +++ /dev/null @@ -1 +0,0 @@ -- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) diff --git a/changelog.d/fixes/8396-cooldown-429-cap.md b/changelog.d/fixes/8396-cooldown-429-cap.md deleted file mode 100644 index 684e2e1f6f..0000000000 --- a/changelog.d/fixes/8396-cooldown-429-cap.md +++ /dev/null @@ -1 +0,0 @@ -- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) diff --git a/changelog.d/fixes/8429-capability-alias-canonicalization.md b/changelog.d/fixes/8429-capability-alias-canonicalization.md deleted file mode 100644 index 6d8d49d8e1..0000000000 --- a/changelog.d/fixes/8429-capability-alias-canonicalization.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) diff --git a/changelog.d/fixes/8431-multiwindow-quota-eviction.md b/changelog.d/fixes/8431-multiwindow-quota-eviction.md deleted file mode 100644 index 9db9be88f5..0000000000 --- a/changelog.d/fixes/8431-multiwindow-quota-eviction.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) diff --git a/changelog.d/fixes/8466-agentbridge-dns-per-agent.md b/changelog.d/fixes/8466-agentbridge-dns-per-agent.md deleted file mode 100644 index 96e0f8e751..0000000000 --- a/changelog.d/fixes/8466-agentbridge-dns-per-agent.md +++ /dev/null @@ -1 +0,0 @@ -- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) diff --git a/changelog.d/fixes/8467-opencode-extra-keys.md b/changelog.d/fixes/8467-opencode-extra-keys.md deleted file mode 100644 index 91dec8f5fc..0000000000 --- a/changelog.d/fixes/8467-opencode-extra-keys.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda diff --git a/changelog.d/fixes/8486-combo-unavailable-field-mismatch.md b/changelog.d/fixes/8486-combo-unavailable-field-mismatch.md deleted file mode 100644 index e0d6826fed..0000000000 --- a/changelog.d/fixes/8486-combo-unavailable-field-mismatch.md +++ /dev/null @@ -1 +0,0 @@ -- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) diff --git a/changelog.d/fixes/8488-capability-filter-fail-closed.md b/changelog.d/fixes/8488-capability-filter-fail-closed.md deleted file mode 100644 index f5487c0e13..0000000000 --- a/changelog.d/fixes/8488-capability-filter-fail-closed.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda diff --git a/changelog.d/fixes/8491-antigravity-projectid-persist.md b/changelog.d/fixes/8491-antigravity-projectid-persist.md deleted file mode 100644 index 71ef22b43f..0000000000 --- a/changelog.d/fixes/8491-antigravity-projectid-persist.md +++ /dev/null @@ -1 +0,0 @@ -- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) diff --git a/changelog.d/fixes/8512-backup-option-shadowing.md b/changelog.d/fixes/8512-backup-option-shadowing.md deleted file mode 100644 index 4e7c19f1e5..0000000000 --- a/changelog.d/fixes/8512-backup-option-shadowing.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded diff --git a/changelog.d/fixes/8514-display-base-url-basepath.md b/changelog.d/fixes/8514-display-base-url-basepath.md deleted file mode 100644 index 14cd8aa1f5..0000000000 --- a/changelog.d/fixes/8514-display-base-url-basepath.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh diff --git a/changelog.d/fixes/8515-basepath-client-fetch.md b/changelog.d/fixes/8515-basepath-client-fetch.md deleted file mode 100644 index 7c1289f161..0000000000 --- a/changelog.d/fixes/8515-basepath-client-fetch.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh diff --git a/changelog.d/fixes/8519-termux-android-cache-dir.md b/changelog.d/fixes/8519-termux-android-cache-dir.md deleted file mode 100644 index e92c18588c..0000000000 --- a/changelog.d/fixes/8519-termux-android-cache-dir.md +++ /dev/null @@ -1 +0,0 @@ -- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) diff --git a/changelog.d/fixes/8530-combo-model-name-collision.md b/changelog.d/fixes/8530-combo-model-name-collision.md deleted file mode 100644 index 65e70c5524..0000000000 --- a/changelog.d/fixes/8530-combo-model-name-collision.md +++ /dev/null @@ -1 +0,0 @@ -- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) diff --git a/changelog.d/fixes/8565-kiro-auth-quota-model-discovery.md b/changelog.d/fixes/8565-kiro-auth-quota-model-discovery.md deleted file mode 100644 index 2f01eed597..0000000000 --- a/changelog.d/fixes/8565-kiro-auth-quota-model-discovery.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 diff --git a/changelog.d/fixes/8568-context-manager-data-dir.md b/changelog.d/fixes/8568-context-manager-data-dir.md deleted file mode 100644 index 9d342b5f40..0000000000 --- a/changelog.d/fixes/8568-context-manager-data-dir.md +++ /dev/null @@ -1 +0,0 @@ -- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync diff --git a/changelog.d/fixes/8589-file-size-update-remove-at-cap.md b/changelog.d/fixes/8589-file-size-update-remove-at-cap.md deleted file mode 100644 index 26118ff27d..0000000000 --- a/changelog.d/fixes/8589-file-size-update-remove-at-cap.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW diff --git a/changelog.d/fixes/8604-task-routing-config-restore.md b/changelog.d/fixes/8604-task-routing-config-restore.md deleted file mode 100644 index 9a7ff6959a..0000000000 --- a/changelog.d/fixes/8604-task-routing-config-restore.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW diff --git a/changelog.d/fixes/8605-task-routing-auto-intent-fitness.md b/changelog.d/fixes/8605-task-routing-auto-intent-fitness.md deleted file mode 100644 index 0a984f5566..0000000000 --- a/changelog.d/fixes/8605-task-routing-auto-intent-fitness.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW diff --git a/changelog.d/fixes/8610-opencode-go-effort-catalog.md b/changelog.d/fixes/8610-opencode-go-effort-catalog.md deleted file mode 100644 index 4228bdc40c..0000000000 --- a/changelog.d/fixes/8610-opencode-go-effort-catalog.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). diff --git a/changelog.d/fixes/8613-local-queue-timeout.md b/changelog.d/fixes/8613-local-queue-timeout.md deleted file mode 100644 index 403e355c9d..0000000000 --- a/changelog.d/fixes/8613-local-queue-timeout.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). diff --git a/changelog.d/fixes/8615-docker-basepath-bundle-patch.md b/changelog.d/fixes/8615-docker-basepath-bundle-patch.md deleted file mode 100644 index c3b57cba74..0000000000 --- a/changelog.d/fixes/8615-docker-basepath-bundle-patch.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev diff --git a/changelog.d/fixes/8616-rate-limit-state-instrumentation.md b/changelog.d/fixes/8616-rate-limit-state-instrumentation.md deleted file mode 100644 index 4df30d5678..0000000000 --- a/changelog.d/fixes/8616-rate-limit-state-instrumentation.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). diff --git a/changelog.d/fixes/8632-kimi-quota-reset-recovery.md b/changelog.d/fixes/8632-kimi-quota-reset-recovery.md deleted file mode 100644 index 80a45aa1d3..0000000000 --- a/changelog.d/fixes/8632-kimi-quota-reset-recovery.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec diff --git a/changelog.d/fixes/8688-gitlab-duo-oauth-setup.md b/changelog.d/fixes/8688-gitlab-duo-oauth-setup.md deleted file mode 100644 index 7cdf3643f2..0000000000 --- a/changelog.d/fixes/8688-gitlab-duo-oauth-setup.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) diff --git a/changelog.d/fixes/8716-combo-compression-null-provider.md b/changelog.d/fixes/8716-combo-compression-null-provider.md deleted file mode 100644 index 84534cf605..0000000000 --- a/changelog.d/fixes/8716-combo-compression-null-provider.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev diff --git a/changelog.d/fixes/8724-native-sqlite-fallback.md b/changelog.d/fixes/8724-native-sqlite-fallback.md deleted file mode 100644 index 4c09beb743..0000000000 --- a/changelog.d/fixes/8724-native-sqlite-fallback.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards diff --git a/changelog.d/fixes/8756-resource-404-health.md b/changelog.d/fixes/8756-resource-404-health.md deleted file mode 100644 index 0fb18aab21..0000000000 --- a/changelog.d/fixes/8756-resource-404-health.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) diff --git a/changelog.d/fixes/8833-models-catalog-cache-ttl.md b/changelog.d/fixes/8833-models-catalog-cache-ttl.md deleted file mode 100644 index 278de5d984..0000000000 --- a/changelog.d/fixes/8833-models-catalog-cache-ttl.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) diff --git a/changelog.d/fixes/8835-ghe-copilot-responses-routing.md b/changelog.d/fixes/8835-ghe-copilot-responses-routing.md deleted file mode 100644 index 68489b4649..0000000000 --- a/changelog.d/fixes/8835-ghe-copilot-responses-routing.md +++ /dev/null @@ -1 +0,0 @@ -- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` diff --git a/changelog.d/fixes/8837-cli-launch-windows-spawn.md b/changelog.d/fixes/8837-cli-launch-windows-spawn.md deleted file mode 100644 index 7381ce340e..0000000000 --- a/changelog.d/fixes/8837-cli-launch-windows-spawn.md +++ /dev/null @@ -1 +0,0 @@ -- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first diff --git a/changelog.d/fixes/8838-codex-gpt56-context-window.md b/changelog.d/fixes/8838-codex-gpt56-context-window.md deleted file mode 100644 index 73741180e5..0000000000 --- a/changelog.d/fixes/8838-codex-gpt56-context-window.md +++ /dev/null @@ -1 +0,0 @@ -- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged diff --git a/changelog.d/fixes/8842-antigravity-projectid-refresh.md b/changelog.d/fixes/8842-antigravity-projectid-refresh.md deleted file mode 100644 index 02a2a85353..0000000000 --- a/changelog.d/fixes/8842-antigravity-projectid-refresh.md +++ /dev/null @@ -1 +0,0 @@ -- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry diff --git a/changelog.d/fixes/8844-tracked-artifacts-ls-files-buffer.md b/changelog.d/fixes/8844-tracked-artifacts-ls-files-buffer.md deleted file mode 100644 index e6c649307d..0000000000 --- a/changelog.d/fixes/8844-tracked-artifacts-ls-files-buffer.md +++ /dev/null @@ -1 +0,0 @@ -- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo diff --git a/changelog.d/fixes/8845-oauth-web-client-type.md b/changelog.d/fixes/8845-oauth-web-client-type.md deleted file mode 100644 index a7e6f77536..0000000000 --- a/changelog.d/fixes/8845-oauth-web-client-type.md +++ /dev/null @@ -1 +0,0 @@ -- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched diff --git a/changelog.d/fixes/8852-vertex-claude-partner-models.md b/changelog.d/fixes/8852-vertex-claude-partner-models.md deleted file mode 100644 index b5b616fd47..0000000000 --- a/changelog.d/fixes/8852-vertex-claude-partner-models.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 diff --git a/changelog.d/fixes/8856-cli-launch-codex-windows-spawn.md b/changelog.d/fixes/8856-cli-launch-codex-windows-spawn.md deleted file mode 100644 index 898b82f8fa..0000000000 --- a/changelog.d/fixes/8856-cli-launch-codex-windows-spawn.md +++ /dev/null @@ -1 +0,0 @@ -- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing diff --git a/changelog.d/fixes/agy-live-model-sync.md b/changelog.d/fixes/agy-live-model-sync.md deleted file mode 100644 index d80b5e68e1..0000000000 --- a/changelog.d/fixes/agy-live-model-sync.md +++ /dev/null @@ -1 +0,0 @@ -- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback diff --git a/changelog.d/fixes/codeql-redos-adobe-jwt.md b/changelog.d/fixes/codeql-redos-adobe-jwt.md deleted file mode 100644 index eb90af0f08..0000000000 --- a/changelog.d/fixes/codeql-redos-adobe-jwt.md +++ /dev/null @@ -1 +0,0 @@ -- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) diff --git a/changelog.d/fixes/codex-nonstream-body-double-read.md b/changelog.d/fixes/codex-nonstream-body-double-read.md deleted file mode 100644 index 143eb47edb..0000000000 --- a/changelog.d/fixes/codex-nonstream-body-double-read.md +++ /dev/null @@ -1 +0,0 @@ -- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. diff --git a/changelog.d/fixes/console-interceptor-epipe-log-flood.md b/changelog.d/fixes/console-interceptor-epipe-log-flood.md deleted file mode 100644 index 8fe139afc6..0000000000 --- a/changelog.d/fixes/console-interceptor-epipe-log-flood.md +++ /dev/null @@ -1 +0,0 @@ -- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) diff --git a/changelog.d/fixes/docs-fabricated-claims.md b/changelog.d/fixes/docs-fabricated-claims.md deleted file mode 100644 index 3ce5275423..0000000000 --- a/changelog.d/fixes/docs-fabricated-claims.md +++ /dev/null @@ -1 +0,0 @@ -- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) diff --git a/changelog.d/fixes/kimi-banner-client-build.md b/changelog.d/fixes/kimi-banner-client-build.md deleted file mode 100644 index 5f4d1a64a4..0000000000 --- a/changelog.d/fixes/kimi-banner-client-build.md +++ /dev/null @@ -1 +0,0 @@ -- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. diff --git a/changelog.d/fixes/mitm-dns-test-root-sudo-strip.md b/changelog.d/fixes/mitm-dns-test-root-sudo-strip.md deleted file mode 100644 index 4da821d214..0000000000 --- a/changelog.d/fixes/mitm-dns-test-root-sudo-strip.md +++ /dev/null @@ -1 +0,0 @@ -- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). diff --git a/changelog.d/fixes/muse-spark-401-cookie-hint.md b/changelog.d/fixes/muse-spark-401-cookie-hint.md deleted file mode 100644 index 685d7d2926..0000000000 --- a/changelog.d/fixes/muse-spark-401-cookie-hint.md +++ /dev/null @@ -1 +0,0 @@ -- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. diff --git a/changelog.d/fixes/notion-thread-idor-hardening.md b/changelog.d/fixes/notion-thread-idor-hardening.md deleted file mode 100644 index 24909ac462..0000000000 --- a/changelog.d/fixes/notion-thread-idor-hardening.md +++ /dev/null @@ -1 +0,0 @@ -- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). diff --git a/changelog.d/fixes/oidc-callback-security-hardening.md b/changelog.d/fixes/oidc-callback-security-hardening.md deleted file mode 100644 index bc719f2e9f..0000000000 --- a/changelog.d/fixes/oidc-callback-security-hardening.md +++ /dev/null @@ -1 +0,0 @@ -- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header diff --git a/changelog.d/fixes/pack-boot-runtimetimeouts-sibling.md b/changelog.d/fixes/pack-boot-runtimetimeouts-sibling.md deleted file mode 100644 index 3fd32f4f02..0000000000 --- a/changelog.d/fixes/pack-boot-runtimetimeouts-sibling.md +++ /dev/null @@ -1 +0,0 @@ -- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers diff --git a/changelog.d/fixes/pack-boot-smoke-gate.md b/changelog.d/fixes/pack-boot-smoke-gate.md deleted file mode 100644 index cc44649218..0000000000 --- a/changelog.d/fixes/pack-boot-smoke-gate.md +++ /dev/null @@ -1 +0,0 @@ -- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` diff --git a/changelog.d/fixes/pack-entrypoint-closures.md b/changelog.d/fixes/pack-entrypoint-closures.md deleted file mode 100644 index 09e114614d..0000000000 --- a/changelog.d/fixes/pack-entrypoint-closures.md +++ /dev/null @@ -1 +0,0 @@ -- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) diff --git a/changelog.d/fixes/pending-cli-service-detection.md b/changelog.d/fixes/pending-cli-service-detection.md deleted file mode 100644 index f9752264d4..0000000000 --- a/changelog.d/fixes/pending-cli-service-detection.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. diff --git a/changelog.d/fixes/pending-podman-machine-guidance.md b/changelog.d/fixes/pending-podman-machine-guidance.md deleted file mode 100644 index a71b24db68..0000000000 --- a/changelog.d/fixes/pending-podman-machine-guidance.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). diff --git a/changelog.d/fixes/pending-react-flow-dark-theme.md b/changelog.d/fixes/pending-react-flow-dark-theme.md deleted file mode 100644 index 1e177ee735..0000000000 --- a/changelog.d/fixes/pending-react-flow-dark-theme.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. diff --git a/changelog.d/fixes/plugin-host-script-sync-delete.md b/changelog.d/fixes/plugin-host-script-sync-delete.md deleted file mode 100644 index 9045669adb..0000000000 --- a/changelog.d/fixes/plugin-host-script-sync-delete.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes diff --git a/changelog.d/fixes/port-2132-headroom-developer-role.md b/changelog.d/fixes/port-2132-headroom-developer-role.md deleted file mode 100644 index c9064e43c5..0000000000 --- a/changelog.d/fixes/port-2132-headroom-developer-role.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) diff --git a/changelog.d/fixes/register-cli-skill-collector.md b/changelog.d/fixes/register-cli-skill-collector.md deleted file mode 100644 index f7ba19ba92..0000000000 --- a/changelog.d/fixes/register-cli-skill-collector.md +++ /dev/null @@ -1 +0,0 @@ -- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) diff --git a/changelog.d/fixes/responses-additional-tools.md b/changelog.d/fixes/responses-additional-tools.md deleted file mode 100644 index a340625de7..0000000000 --- a/changelog.d/fixes/responses-additional-tools.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. diff --git a/changelog.d/fixes/responses-think-close-marker.md b/changelog.d/fixes/responses-think-close-marker.md deleted file mode 100644 index 0d5177ec33..0000000000 --- a/changelog.d/fixes/responses-think-close-marker.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. diff --git a/changelog.d/fixes/sec-adm-zip-codeql-host-match.md b/changelog.d/fixes/sec-adm-zip-codeql-host-match.md deleted file mode 100644 index e1b3a8f4dc..0000000000 --- a/changelog.d/fixes/sec-adm-zip-codeql-host-match.md +++ /dev/null @@ -1 +0,0 @@ -- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) diff --git a/changelog.d/fixes/sec-deps-dependabot-7.md b/changelog.d/fixes/sec-deps-dependabot-7.md deleted file mode 100644 index f59cc71bd7..0000000000 --- a/changelog.d/fixes/sec-deps-dependabot-7.md +++ /dev/null @@ -1 +0,0 @@ -- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts diff --git a/changelog.d/fixes/sec-deps2-dependabot-3.md b/changelog.d/fixes/sec-deps2-dependabot-3.md deleted file mode 100644 index cd965a597c..0000000000 --- a/changelog.d/fixes/sec-deps2-dependabot-3.md +++ /dev/null @@ -1 +0,0 @@ -- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts diff --git a/changelog.d/fixes/stryker-testfiles-drift.md b/changelog.d/fixes/stryker-testfiles-drift.md deleted file mode 100644 index b713390340..0000000000 --- a/changelog.d/fixes/stryker-testfiles-drift.md +++ /dev/null @@ -1 +0,0 @@ -- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) diff --git a/changelog.d/fixes/tokenhealthcheck-tickms.md b/changelog.d/fixes/tokenhealthcheck-tickms.md deleted file mode 100644 index 40bda89fc7..0000000000 --- a/changelog.d/fixes/tokenhealthcheck-tickms.md +++ /dev/null @@ -1 +0,0 @@ -- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup diff --git a/changelog.d/fixes/vision-bridge-no-credentialed-hijack.md b/changelog.d/fixes/vision-bridge-no-credentialed-hijack.md deleted file mode 100644 index 637d661ea8..0000000000 --- a/changelog.d/fixes/vision-bridge-no-credentialed-hijack.md +++ /dev/null @@ -1 +0,0 @@ -- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header \ No newline at end of file diff --git a/changelog.d/fixes/yuanbao-cookie-validation.md b/changelog.d/fixes/yuanbao-cookie-validation.md deleted file mode 100644 index eb91b6edba..0000000000 --- a/changelog.d/fixes/yuanbao-cookie-validation.md +++ /dev/null @@ -1 +0,0 @@ -- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip diff --git a/changelog.d/maintenance/6784-merge-train.md b/changelog.d/maintenance/6784-merge-train.md deleted file mode 100644 index e98586183f..0000000000 --- a/changelog.d/maintenance/6784-merge-train.md +++ /dev/null @@ -1 +0,0 @@ -- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. diff --git a/changelog.d/maintenance/6878-list-uncovered-fragments.md b/changelog.d/maintenance/6878-list-uncovered-fragments.md deleted file mode 100644 index de5fb61642..0000000000 --- a/changelog.d/maintenance/6878-list-uncovered-fragments.md +++ /dev/null @@ -1 +0,0 @@ -- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) diff --git a/changelog.d/maintenance/7068-dependabot-ignore-typescript-major.md b/changelog.d/maintenance/7068-dependabot-ignore-typescript-major.md deleted file mode 100644 index ae20696c5e..0000000000 --- a/changelog.d/maintenance/7068-dependabot-ignore-typescript-major.md +++ /dev/null @@ -1 +0,0 @@ -- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. diff --git a/changelog.d/maintenance/7213-7603-filesize-baseline.md b/changelog.d/maintenance/7213-7603-filesize-baseline.md deleted file mode 100644 index 3db9a6b953..0000000000 --- a/changelog.d/maintenance/7213-7603-filesize-baseline.md +++ /dev/null @@ -1 +0,0 @@ -- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. diff --git a/changelog.d/maintenance/7251-vi-quota-visibility-keys.md b/changelog.d/maintenance/7251-vi-quota-visibility-keys.md deleted file mode 100644 index ea3f1947de..0000000000 --- a/changelog.d/maintenance/7251-vi-quota-visibility-keys.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. diff --git a/changelog.d/maintenance/7287-codex-long-running-tasks.md b/changelog.d/maintenance/7287-codex-long-running-tasks.md deleted file mode 100644 index 7255fa1466..0000000000 --- a/changelog.d/maintenance/7287-codex-long-running-tasks.md +++ /dev/null @@ -1 +0,0 @@ -- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) diff --git a/changelog.d/maintenance/7291-quota-card-grid-density-6815-guard.md b/changelog.d/maintenance/7291-quota-card-grid-density-6815-guard.md deleted file mode 100644 index 6652969e7d..0000000000 --- a/changelog.d/maintenance/7291-quota-card-grid-density-6815-guard.md +++ /dev/null @@ -1 +0,0 @@ -- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) diff --git a/changelog.d/maintenance/7295-avast-readme-false-positive.md b/changelog.d/maintenance/7295-avast-readme-false-positive.md deleted file mode 100644 index f51a9bf9ce..0000000000 --- a/changelog.d/maintenance/7295-avast-readme-false-positive.md +++ /dev/null @@ -1 +0,0 @@ -- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) diff --git a/changelog.d/maintenance/7307-rehome-open-prs-script.md b/changelog.d/maintenance/7307-rehome-open-prs-script.md deleted file mode 100644 index e20161f4bc..0000000000 --- a/changelog.d/maintenance/7307-rehome-open-prs-script.md +++ /dev/null @@ -1 +0,0 @@ -- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. diff --git a/changelog.d/maintenance/7307-release-pr-build-gate.md b/changelog.d/maintenance/7307-release-pr-build-gate.md deleted file mode 100644 index 943b08b590..0000000000 --- a/changelog.d/maintenance/7307-release-pr-build-gate.md +++ /dev/null @@ -1,2 +0,0 @@ -- Add an advisory production build to the PR-to-release quality workflow for non-draft code - changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. diff --git a/changelog.d/maintenance/7334-incident-response-runbook.md b/changelog.d/maintenance/7334-incident-response-runbook.md deleted file mode 100644 index 32a2286cff..0000000000 --- a/changelog.d/maintenance/7334-incident-response-runbook.md +++ /dev/null @@ -1 +0,0 @@ -- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari diff --git a/changelog.d/maintenance/7336-perf-latency-budgets-doc.md b/changelog.d/maintenance/7336-perf-latency-budgets-doc.md deleted file mode 100644 index a74a2a670a..0000000000 --- a/changelog.d/maintenance/7336-perf-latency-budgets-doc.md +++ /dev/null @@ -1 +0,0 @@ -- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari diff --git a/changelog.d/maintenance/7615-readme-tier-cascade-svg.md b/changelog.d/maintenance/7615-readme-tier-cascade-svg.md deleted file mode 100644 index 593427f876..0000000000 --- a/changelog.d/maintenance/7615-readme-tier-cascade-svg.md +++ /dev/null @@ -1 +0,0 @@ -- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). diff --git a/changelog.d/maintenance/7616-docs-provider-count-259.md b/changelog.d/maintenance/7616-docs-provider-count-259.md deleted file mode 100644 index 8efbcae35f..0000000000 --- a/changelog.d/maintenance/7616-docs-provider-count-259.md +++ /dev/null @@ -1 +0,0 @@ -- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). diff --git a/changelog.d/maintenance/7626-readme-pool-combo-svg.md b/changelog.d/maintenance/7626-readme-pool-combo-svg.md deleted file mode 100644 index 14ebdc8f25..0000000000 --- a/changelog.d/maintenance/7626-readme-pool-combo-svg.md +++ /dev/null @@ -1 +0,0 @@ -- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. diff --git a/changelog.d/maintenance/7627-branching-model-doc.md b/changelog.d/maintenance/7627-branching-model-doc.md deleted file mode 100644 index 340834d308..0000000000 --- a/changelog.d/maintenance/7627-branching-model-doc.md +++ /dev/null @@ -1 +0,0 @@ -- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal diff --git a/changelog.d/maintenance/7637-readme-cli-compression-svg.md b/changelog.d/maintenance/7637-readme-cli-compression-svg.md deleted file mode 100644 index e71439fcc6..0000000000 --- a/changelog.d/maintenance/7637-readme-cli-compression-svg.md +++ /dev/null @@ -1 +0,0 @@ -- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. diff --git a/changelog.d/maintenance/7665-readme-free-tier-budget-svg.md b/changelog.d/maintenance/7665-readme-free-tier-budget-svg.md deleted file mode 100644 index fd25865e8f..0000000000 --- a/changelog.d/maintenance/7665-readme-free-tier-budget-svg.md +++ /dev/null @@ -1 +0,0 @@ -- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) diff --git a/changelog.d/maintenance/7666-readme-tables-full-width.md b/changelog.d/maintenance/7666-readme-tables-full-width.md deleted file mode 100644 index bf790a5041..0000000000 --- a/changelog.d/maintenance/7666-readme-tables-full-width.md +++ /dev/null @@ -1 +0,0 @@ -- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) diff --git a/changelog.d/maintenance/7690-basered-full-suite-realignment.md b/changelog.d/maintenance/7690-basered-full-suite-realignment.md deleted file mode 100644 index b95e13a7d7..0000000000 --- a/changelog.d/maintenance/7690-basered-full-suite-realignment.md +++ /dev/null @@ -1 +0,0 @@ -- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. diff --git a/changelog.d/maintenance/7769-readme-animated-cards-overhaul.md b/changelog.d/maintenance/7769-readme-animated-cards-overhaul.md deleted file mode 100644 index 56e757fe3b..0000000000 --- a/changelog.d/maintenance/7769-readme-animated-cards-overhaul.md +++ /dev/null @@ -1 +0,0 @@ -- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) diff --git a/changelog.d/maintenance/7838-7806-basereds-case-collision-stryker.md b/changelog.d/maintenance/7838-7806-basereds-case-collision-stryker.md deleted file mode 100644 index 7f82286fbe..0000000000 --- a/changelog.d/maintenance/7838-7806-basereds-case-collision-stryker.md +++ /dev/null @@ -1 +0,0 @@ -- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. diff --git a/changelog.d/maintenance/7838-vi-tier-override-keys.md b/changelog.d/maintenance/7838-vi-tier-override-keys.md deleted file mode 100644 index fc03db3b17..0000000000 --- a/changelog.d/maintenance/7838-vi-tier-override-keys.md +++ /dev/null @@ -1 +0,0 @@ -- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. diff --git a/changelog.d/maintenance/7840-golden-translate-path-regen.md b/changelog.d/maintenance/7840-golden-translate-path-regen.md deleted file mode 100644 index ffdd06e743..0000000000 --- a/changelog.d/maintenance/7840-golden-translate-path-regen.md +++ /dev/null @@ -1 +0,0 @@ -- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. diff --git a/changelog.d/maintenance/7843-prune-stale-eslint-suppression.md b/changelog.d/maintenance/7843-prune-stale-eslint-suppression.md deleted file mode 100644 index 34e62aac3a..0000000000 --- a/changelog.d/maintenance/7843-prune-stale-eslint-suppression.md +++ /dev/null @@ -1 +0,0 @@ -- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. diff --git a/changelog.d/maintenance/8058-dispatchcompression-complexity.md b/changelog.d/maintenance/8058-dispatchcompression-complexity.md deleted file mode 100644 index 251390c237..0000000000 --- a/changelog.d/maintenance/8058-dispatchcompression-complexity.md +++ /dev/null @@ -1 +0,0 @@ -- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). diff --git a/changelog.d/maintenance/8566-basered-rebaseline-mergequeue.md b/changelog.d/maintenance/8566-basered-rebaseline-mergequeue.md deleted file mode 100644 index a7afbb10f9..0000000000 --- a/changelog.d/maintenance/8566-basered-rebaseline-mergequeue.md +++ /dev/null @@ -1 +0,0 @@ -- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). diff --git a/changelog.d/maintenance/8582-combo-dispatch-prelude.md b/changelog.d/maintenance/8582-combo-dispatch-prelude.md deleted file mode 100644 index 789c07d354..0000000000 --- a/changelog.d/maintenance/8582-combo-dispatch-prelude.md +++ /dev/null @@ -1 +0,0 @@ -- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW diff --git a/changelog.d/maintenance/8585-file-size-bank-completed-shrinks.md b/changelog.d/maintenance/8585-file-size-bank-completed-shrinks.md deleted file mode 100644 index 57245678f2..0000000000 --- a/changelog.d/maintenance/8585-file-size-bank-completed-shrinks.md +++ /dev/null @@ -1 +0,0 @@ -- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW diff --git a/changelog.d/maintenance/8592-combo-target-resolution.md b/changelog.d/maintenance/8592-combo-target-resolution.md deleted file mode 100644 index dfb8efd2b2..0000000000 --- a/changelog.d/maintenance/8592-combo-target-resolution.md +++ /dev/null @@ -1 +0,0 @@ -- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW diff --git a/changelog.d/maintenance/8619-source-scanner-negative-guards.md b/changelog.d/maintenance/8619-source-scanner-negative-guards.md deleted file mode 100644 index fc65a90710..0000000000 --- a/changelog.d/maintenance/8619-source-scanner-negative-guards.md +++ /dev/null @@ -1 +0,0 @@ -- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. diff --git a/changelog.d/maintenance/8657-agent-skills-cli-backup-sync-stale.md b/changelog.d/maintenance/8657-agent-skills-cli-backup-sync-stale.md deleted file mode 100644 index bdb8f7b873..0000000000 --- a/changelog.d/maintenance/8657-agent-skills-cli-backup-sync-stale.md +++ /dev/null @@ -1 +0,0 @@ -- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW diff --git a/changelog.d/maintenance/agentrouter-test-import-chain.md b/changelog.d/maintenance/agentrouter-test-import-chain.md deleted file mode 100644 index 432b4e83be..0000000000 --- a/changelog.d/maintenance/agentrouter-test-import-chain.md +++ /dev/null @@ -1 +0,0 @@ -- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) diff --git a/changelog.d/maintenance/antigravity-nonstream-test-realign.md b/changelog.d/maintenance/antigravity-nonstream-test-realign.md deleted file mode 100644 index b116718b81..0000000000 --- a/changelog.d/maintenance/antigravity-nonstream-test-realign.md +++ /dev/null @@ -1 +0,0 @@ -- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). diff --git a/changelog.d/maintenance/basereds-captain-2026-07-12.md b/changelog.d/maintenance/basereds-captain-2026-07-12.md deleted file mode 100644 index b8d359a762..0000000000 --- a/changelog.d/maintenance/basereds-captain-2026-07-12.md +++ /dev/null @@ -1 +0,0 @@ -- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) diff --git a/changelog.d/maintenance/basereds-i18n-gemini-2026-07-13.md b/changelog.d/maintenance/basereds-i18n-gemini-2026-07-13.md deleted file mode 100644 index cdadafc8b6..0000000000 --- a/changelog.d/maintenance/basereds-i18n-gemini-2026-07-13.md +++ /dev/null @@ -1 +0,0 @@ -- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract diff --git a/changelog.d/maintenance/basereds-mechanical-2026-07-12.md b/changelog.d/maintenance/basereds-mechanical-2026-07-12.md deleted file mode 100644 index f1ee83c06f..0000000000 --- a/changelog.d/maintenance/basereds-mechanical-2026-07-12.md +++ /dev/null @@ -1 +0,0 @@ -- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) diff --git a/changelog.d/maintenance/chatcore-compression-itest-ctx-boundary.md b/changelog.d/maintenance/chatcore-compression-itest-ctx-boundary.md deleted file mode 100644 index 18c38ce8ad..0000000000 --- a/changelog.d/maintenance/chatcore-compression-itest-ctx-boundary.md +++ /dev/null @@ -1 +0,0 @@ -- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch diff --git a/changelog.d/maintenance/ci-pr-test-policy-shallow-base.md b/changelog.d/maintenance/ci-pr-test-policy-shallow-base.md deleted file mode 100644 index 340b60a5ce..0000000000 --- a/changelog.d/maintenance/ci-pr-test-policy-shallow-base.md +++ /dev/null @@ -1 +0,0 @@ -- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). diff --git a/changelog.d/maintenance/ci-vps-runner-sharding.md b/changelog.d/maintenance/ci-vps-runner-sharding.md deleted file mode 100644 index 925ce479a4..0000000000 --- a/changelog.d/maintenance/ci-vps-runner-sharding.md +++ /dev/null @@ -1 +0,0 @@ -- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). diff --git a/changelog.d/maintenance/codecov-patch-coverage.md b/changelog.d/maintenance/codecov-patch-coverage.md deleted file mode 100644 index 6d023220d6..0000000000 --- a/changelog.d/maintenance/codecov-patch-coverage.md +++ /dev/null @@ -1 +0,0 @@ -- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) diff --git a/changelog.d/maintenance/combo-harness-host-classification.md b/changelog.d/maintenance/combo-harness-host-classification.md deleted file mode 100644 index 6a7243c456..0000000000 --- a/changelog.d/maintenance/combo-harness-host-classification.md +++ /dev/null @@ -1 +0,0 @@ -- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. diff --git a/changelog.d/maintenance/combo-predicates-extract.md b/changelog.d/maintenance/combo-predicates-extract.md deleted file mode 100644 index a469a43550..0000000000 --- a/changelog.d/maintenance/combo-predicates-extract.md +++ /dev/null @@ -1 +0,0 @@ -- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. diff --git a/changelog.d/maintenance/coverage-job-timeout.md b/changelog.d/maintenance/coverage-job-timeout.md deleted file mode 100644 index ce36f15f3f..0000000000 --- a/changelog.d/maintenance/coverage-job-timeout.md +++ /dev/null @@ -1 +0,0 @@ -- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" diff --git a/changelog.d/maintenance/dast-smoke-timeout.md b/changelog.d/maintenance/dast-smoke-timeout.md deleted file mode 100644 index b8c9880570..0000000000 --- a/changelog.d/maintenance/dast-smoke-timeout.md +++ /dev/null @@ -1 +0,0 @@ -- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) diff --git a/changelog.d/maintenance/decomp-provider-validation.md b/changelog.d/maintenance/decomp-provider-validation.md deleted file mode 100644 index 0514896b83..0000000000 --- a/changelog.d/maintenance/decomp-provider-validation.md +++ /dev/null @@ -1 +0,0 @@ -- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site diff --git a/changelog.d/maintenance/decomp-token-refresh.md b/changelog.d/maintenance/decomp-token-refresh.md deleted file mode 100644 index f9bc03062b..0000000000 --- a/changelog.d/maintenance/decomp-token-refresh.md +++ /dev/null @@ -1 +0,0 @@ -- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged diff --git a/changelog.d/maintenance/decomp-usage-service.md b/changelog.d/maintenance/decomp-usage-service.md deleted file mode 100644 index 55806cc43b..0000000000 --- a/changelog.d/maintenance/decomp-usage-service.md +++ /dev/null @@ -1 +0,0 @@ -- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged diff --git a/changelog.d/maintenance/docs-strategy-count-skill-names.md b/changelog.d/maintenance/docs-strategy-count-skill-names.md deleted file mode 100644 index a14507159b..0000000000 --- a/changelog.d/maintenance/docs-strategy-count-skill-names.md +++ /dev/null @@ -1 +0,0 @@ -- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). diff --git a/changelog.d/maintenance/e2e-shard-balance.md b/changelog.d/maintenance/e2e-shard-balance.md deleted file mode 100644 index a950f1ba44..0000000000 --- a/changelog.d/maintenance/e2e-shard-balance.md +++ /dev/null @@ -1 +0,0 @@ -- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency diff --git a/changelog.d/maintenance/electron-win-advisory.md b/changelog.d/maintenance/electron-win-advisory.md deleted file mode 100644 index c5f29e8404..0000000000 --- a/changelog.d/maintenance/electron-win-advisory.md +++ /dev/null @@ -1 +0,0 @@ -- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green diff --git a/changelog.d/maintenance/electron-win-prepare-smoke.md b/changelog.d/maintenance/electron-win-prepare-smoke.md deleted file mode 100644 index 2fcdfe3740..0000000000 --- a/changelog.d/maintenance/electron-win-prepare-smoke.md +++ /dev/null @@ -1 +0,0 @@ -- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution diff --git a/changelog.d/maintenance/gate-hygiene-secrets-semgrep-hadolint.md b/changelog.d/maintenance/gate-hygiene-secrets-semgrep-hadolint.md deleted file mode 100644 index 7009f36ab2..0000000000 --- a/changelog.d/maintenance/gate-hygiene-secrets-semgrep-hadolint.md +++ /dev/null @@ -1 +0,0 @@ -- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) diff --git a/changelog.d/maintenance/ghe-copilot-registry-mirrors.md b/changelog.d/maintenance/ghe-copilot-registry-mirrors.md deleted file mode 100644 index dbcae31d38..0000000000 --- a/changelog.d/maintenance/ghe-copilot-registry-mirrors.md +++ /dev/null @@ -1,2 +0,0 @@ -- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` -- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind diff --git a/changelog.d/maintenance/heap-benchmark-request-body.md b/changelog.d/maintenance/heap-benchmark-request-body.md deleted file mode 100644 index 46ad07feaa..0000000000 --- a/changelog.d/maintenance/heap-benchmark-request-body.md +++ /dev/null @@ -1 +0,0 @@ -- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition diff --git a/changelog.d/maintenance/hotfix-fastlane.md b/changelog.d/maintenance/hotfix-fastlane.md deleted file mode 100644 index a7110c9a79..0000000000 --- a/changelog.d/maintenance/hotfix-fastlane.md +++ /dev/null @@ -1 +0,0 @@ -- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output diff --git a/changelog.d/maintenance/lint-suppression-resync-proxy-registry.md b/changelog.d/maintenance/lint-suppression-resync-proxy-registry.md deleted file mode 100644 index f6a8269335..0000000000 --- a/changelog.d/maintenance/lint-suppression-resync-proxy-registry.md +++ /dev/null @@ -1 +0,0 @@ -- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it diff --git a/changelog.d/maintenance/merge-train-box-speed.md b/changelog.d/maintenance/merge-train-box-speed.md deleted file mode 100644 index 2eeb17a1a4..0000000000 --- a/changelog.d/maintenance/merge-train-box-speed.md +++ /dev/null @@ -1 +0,0 @@ -- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains diff --git a/changelog.d/maintenance/merge-train-unit-subdir-allowlist.md b/changelog.d/maintenance/merge-train-unit-subdir-allowlist.md deleted file mode 100644 index d9ba696337..0000000000 --- a/changelog.d/maintenance/merge-train-unit-subdir-allowlist.md +++ /dev/null @@ -1,4 +0,0 @@ -- **chore(release):** merge-train `--fast` now classifies changed tests with the same - `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. - `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and - `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. diff --git a/changelog.d/maintenance/mergify-queue-draft-ci.md b/changelog.d/maintenance/mergify-queue-draft-ci.md deleted file mode 100644 index 63469d2c33..0000000000 --- a/changelog.d/maintenance/mergify-queue-draft-ci.md +++ /dev/null @@ -1 +0,0 @@ -- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued diff --git a/changelog.d/maintenance/mergify-queue.md b/changelog.d/maintenance/mergify-queue.md deleted file mode 100644 index 8ffe6bb43a..0000000000 --- a/changelog.d/maintenance/mergify-queue.md +++ /dev/null @@ -1 +0,0 @@ -- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails diff --git a/changelog.d/maintenance/npm-staged-publishing.md b/changelog.d/maintenance/npm-staged-publishing.md deleted file mode 100644 index e57f471083..0000000000 --- a/changelog.d/maintenance/npm-staged-publishing.md +++ /dev/null @@ -1 +0,0 @@ -- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback diff --git a/changelog.d/maintenance/preflight-v3847-2026-07-13.md b/changelog.d/maintenance/preflight-v3847-2026-07-13.md deleted file mode 100644 index ce4e9b6897..0000000000 --- a/changelog.d/maintenance/preflight-v3847-2026-07-13.md +++ /dev/null @@ -1 +0,0 @@ -- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 diff --git a/changelog.d/maintenance/quality-policies-ws5.md b/changelog.d/maintenance/quality-policies-ws5.md deleted file mode 100644 index 990c7e7c20..0000000000 --- a/changelog.d/maintenance/quality-policies-ws5.md +++ /dev/null @@ -1 +0,0 @@ -- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) diff --git a/changelog.d/maintenance/ratchet-rebaseline-2130-950.md b/changelog.d/maintenance/ratchet-rebaseline-2130-950.md deleted file mode 100644 index fc79ee6103..0000000000 --- a/changelog.d/maintenance/ratchet-rebaseline-2130-950.md +++ /dev/null @@ -1 +0,0 @@ -- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) diff --git a/changelog.d/maintenance/readme-strategy-tool-counts.md b/changelog.d/maintenance/readme-strategy-tool-counts.md deleted file mode 100644 index 6e82bd00c1..0000000000 --- a/changelog.d/maintenance/readme-strategy-tool-counts.md +++ /dev/null @@ -1 +0,0 @@ -- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. diff --git a/changelog.d/maintenance/rebaseline-complexity-2072-cognitive-900.md b/changelog.d/maintenance/rebaseline-complexity-2072-cognitive-900.md deleted file mode 100644 index 0fc01e0971..0000000000 --- a/changelog.d/maintenance/rebaseline-complexity-2072-cognitive-900.md +++ /dev/null @@ -1 +0,0 @@ -- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. diff --git a/changelog.d/maintenance/release-green-continuous.md b/changelog.d/maintenance/release-green-continuous.md deleted file mode 100644 index b3c181510d..0000000000 --- a/changelog.d/maintenance/release-green-continuous.md +++ /dev/null @@ -1 +0,0 @@ -- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) diff --git a/changelog.d/maintenance/release-v3.8.47-basereds.md b/changelog.d/maintenance/release-v3.8.47-basereds.md deleted file mode 100644 index 5305f83ac7..0000000000 --- a/changelog.d/maintenance/release-v3.8.47-basereds.md +++ /dev/null @@ -1 +0,0 @@ -- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). diff --git a/changelog.d/maintenance/root-cleanup-llmtxt-design-system.md b/changelog.d/maintenance/root-cleanup-llmtxt-design-system.md deleted file mode 100644 index acaad759f6..0000000000 --- a/changelog.d/maintenance/root-cleanup-llmtxt-design-system.md +++ /dev/null @@ -1 +0,0 @@ -- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. diff --git a/changelog.d/maintenance/router-eval-test-assert-strengthen.md b/changelog.d/maintenance/router-eval-test-assert-strengthen.md deleted file mode 100644 index c6f6e86046..0000000000 --- a/changelog.d/maintenance/router-eval-test-assert-strengthen.md +++ /dev/null @@ -1 +0,0 @@ -- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. diff --git a/changelog.d/maintenance/runner-janitor.md b/changelog.d/maintenance/runner-janitor.md deleted file mode 100644 index 365f4a5b00..0000000000 --- a/changelog.d/maintenance/runner-janitor.md +++ /dev/null @@ -1 +0,0 @@ -- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) diff --git a/changelog.d/maintenance/scrub-boundary-test-creds.md b/changelog.d/maintenance/scrub-boundary-test-creds.md deleted file mode 100644 index e054292504..0000000000 --- a/changelog.d/maintenance/scrub-boundary-test-creds.md +++ /dev/null @@ -1 +0,0 @@ -- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. diff --git a/changelog.d/maintenance/selfref-6634-shallow.md b/changelog.d/maintenance/selfref-6634-shallow.md deleted file mode 100644 index 6f0c1b345a..0000000000 --- a/changelog.d/maintenance/selfref-6634-shallow.md +++ /dev/null @@ -1 +0,0 @@ -- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) diff --git a/changelog.d/maintenance/stryker-register-5-covering-tests.md b/changelog.d/maintenance/stryker-register-5-covering-tests.md deleted file mode 100644 index b614fa9037..0000000000 --- a/changelog.d/maintenance/stryker-register-5-covering-tests.md +++ /dev/null @@ -1 +0,0 @@ -- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. diff --git a/changelog.d/maintenance/stryker-testfiles-6672.md b/changelog.d/maintenance/stryker-testfiles-6672.md deleted file mode 100644 index 586367f4ff..0000000000 --- a/changelog.d/maintenance/stryker-testfiles-6672.md +++ /dev/null @@ -1 +0,0 @@ -- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) diff --git a/changelog.d/maintenance/sync-back-green-gate.md b/changelog.d/maintenance/sync-back-green-gate.md deleted file mode 100644 index 40bded1502..0000000000 --- a/changelog.d/maintenance/sync-back-green-gate.md +++ /dev/null @@ -1 +0,0 @@ -- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) diff --git a/changelog.d/maintenance/testfrozen-providers-page-utils-7775.md b/changelog.d/maintenance/testfrozen-providers-page-utils-7775.md deleted file mode 100644 index 46cbc5a8d6..0000000000 --- a/changelog.d/maintenance/testfrozen-providers-page-utils-7775.md +++ /dev/null @@ -1 +0,0 @@ -- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. diff --git a/changelog.d/maintenance/tighten-coverage-baseline.md b/changelog.d/maintenance/tighten-coverage-baseline.md deleted file mode 100644 index 119eb1c856..0000000000 --- a/changelog.d/maintenance/tighten-coverage-baseline.md +++ /dev/null @@ -1 +0,0 @@ -- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). diff --git a/changelog.d/maintenance/tokenrefresh-provider-extraction.md b/changelog.d/maintenance/tokenrefresh-provider-extraction.md deleted file mode 100644 index a813551b0c..0000000000 --- a/changelog.d/maintenance/tokenrefresh-provider-extraction.md +++ /dev/null @@ -1 +0,0 @@ -- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. diff --git a/changelog.d/maintenance/train1h-ratchet-and-stryker.md b/changelog.d/maintenance/train1h-ratchet-and-stryker.md deleted file mode 100644 index 9dd8a82d0c..0000000000 --- a/changelog.d/maintenance/train1h-ratchet-and-stryker.md +++ /dev/null @@ -1 +0,0 @@ -- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR diff --git a/changelog.d/maintenance/train2-chatcore-ratchet.md b/changelog.d/maintenance/train2-chatcore-ratchet.md deleted file mode 100644 index 441cabe57e..0000000000 --- a/changelog.d/maintenance/train2-chatcore-ratchet.md +++ /dev/null @@ -1 +0,0 @@ -- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 diff --git a/changelog.d/maintenance/train2-pack-artifact-and-ratchet.md b/changelog.d/maintenance/train2-pack-artifact-and-ratchet.md deleted file mode 100644 index c3660af40e..0000000000 --- a/changelog.d/maintenance/train2-pack-artifact-and-ratchet.md +++ /dev/null @@ -1 +0,0 @@ -- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch diff --git a/changelog.d/maintenance/train3-ratchet-and-stryker.md b/changelog.d/maintenance/train3-ratchet-and-stryker.md deleted file mode 100644 index a22b76cd99..0000000000 --- a/changelog.d/maintenance/train3-ratchet-and-stryker.md +++ /dev/null @@ -1 +0,0 @@ -- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` diff --git a/changelog.d/maintenance/trunk-flaky-uploads.md b/changelog.d/maintenance/trunk-flaky-uploads.md deleted file mode 100644 index 89c0e6b853..0000000000 --- a/changelog.d/maintenance/trunk-flaky-uploads.md +++ /dev/null @@ -1 +0,0 @@ -- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) diff --git a/changelog.d/maintenance/trunk-upload-fastpath.md b/changelog.d/maintenance/trunk-upload-fastpath.md deleted file mode 100644 index 441f1300fe..0000000000 --- a/changelog.d/maintenance/trunk-upload-fastpath.md +++ /dev/null @@ -1 +0,0 @@ -- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume diff --git a/changelog.d/maintenance/ts7-shadow-typecheck.md b/changelog.d/maintenance/ts7-shadow-typecheck.md deleted file mode 100644 index e73b70f8de..0000000000 --- a/changelog.d/maintenance/ts7-shadow-typecheck.md +++ /dev/null @@ -1 +0,0 @@ -- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity diff --git a/changelog.d/maintenance/v3849-campaign-basereds.md b/changelog.d/maintenance/v3849-campaign-basereds.md deleted file mode 100644 index a0ff2e4ea8..0000000000 --- a/changelog.d/maintenance/v3849-campaign-basereds.md +++ /dev/null @@ -1 +0,0 @@ -- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. diff --git a/changelog.d/maintenance/verify-published.md b/changelog.d/maintenance/verify-published.md deleted file mode 100644 index 3f244bfd73..0000000000 --- a/changelog.d/maintenance/verify-published.md +++ /dev/null @@ -1 +0,0 @@ -- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook diff --git a/changelog.d/maintenance/vitest-ui-blocking.md b/changelog.d/maintenance/vitest-ui-blocking.md deleted file mode 100644 index 4ed70f7f3c..0000000000 --- a/changelog.d/maintenance/vitest-ui-blocking.md +++ /dev/null @@ -1 +0,0 @@ -- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job diff --git a/changelog.d/maintenance/vitest-ui-suite-green.md b/changelog.d/maintenance/vitest-ui-suite-green.md deleted file mode 100644 index 539058bd72..0000000000 --- a/changelog.d/maintenance/vitest-ui-suite-green.md +++ /dev/null @@ -1 +0,0 @@ -- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) diff --git a/docs/i18n/ar/CHANGELOG.md b/docs/i18n/ar/CHANGELOG.md index 9046b606ca..57c9032620 100644 --- a/docs/i18n/ar/CHANGELOG.md +++ b/docs/i18n/ar/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/bg/CHANGELOG.md b/docs/i18n/bg/CHANGELOG.md index 5fbb32038e..b957151535 100644 --- a/docs/i18n/bg/CHANGELOG.md +++ b/docs/i18n/bg/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/cs/CHANGELOG.md b/docs/i18n/cs/CHANGELOG.md index 4052cf7134..cb444f67d7 100644 --- a/docs/i18n/cs/CHANGELOG.md +++ b/docs/i18n/cs/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/de/CHANGELOG.md b/docs/i18n/de/CHANGELOG.md index ae4274c0e5..535dd4cd50 100644 --- a/docs/i18n/de/CHANGELOG.md +++ b/docs/i18n/de/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/fa/CHANGELOG.md b/docs/i18n/fa/CHANGELOG.md index faa179cd94..2b5731aaa1 100644 --- a/docs/i18n/fa/CHANGELOG.md +++ b/docs/i18n/fa/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/fr/CHANGELOG.md b/docs/i18n/fr/CHANGELOG.md index 605c4a2037..7552398d12 100644 --- a/docs/i18n/fr/CHANGELOG.md +++ b/docs/i18n/fr/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/he/CHANGELOG.md b/docs/i18n/he/CHANGELOG.md index 629a1b403e..c60c772bfd 100644 --- a/docs/i18n/he/CHANGELOG.md +++ b/docs/i18n/he/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/hu/CHANGELOG.md b/docs/i18n/hu/CHANGELOG.md index 398dfe68eb..2b62bcd61d 100644 --- a/docs/i18n/hu/CHANGELOG.md +++ b/docs/i18n/hu/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/in/CHANGELOG.md b/docs/i18n/in/CHANGELOG.md index e18e61ca7f..db0284db20 100644 --- a/docs/i18n/in/CHANGELOG.md +++ b/docs/i18n/in/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/ja/CHANGELOG.md b/docs/i18n/ja/CHANGELOG.md index 967105b3a2..5ef21adfdd 100644 --- a/docs/i18n/ja/CHANGELOG.md +++ b/docs/i18n/ja/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/mr/CHANGELOG.md b/docs/i18n/mr/CHANGELOG.md index 83e1f423a8..0f652a553d 100644 --- a/docs/i18n/mr/CHANGELOG.md +++ b/docs/i18n/mr/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/nl/CHANGELOG.md b/docs/i18n/nl/CHANGELOG.md index b06be5ce83..3f6844ea29 100644 --- a/docs/i18n/nl/CHANGELOG.md +++ b/docs/i18n/nl/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/phi/CHANGELOG.md b/docs/i18n/phi/CHANGELOG.md index 30a927ed54..edc7203769 100644 --- a/docs/i18n/phi/CHANGELOG.md +++ b/docs/i18n/phi/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -173,7 +297,6 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 - ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -508,7 +631,379 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) - **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) - **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) - +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -540,7 +1035,6 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) - ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -553,7 +1047,6 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu - ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -592,7 +1085,6 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) - ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -622,101 +1114,271 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun - **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) - **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] - ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: -| Contributor | PRs / Issues | -| ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | -| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | -| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | -| [@alltomatos](https://github.com/alltomatos) | #7041, #7042, #7164, #7277, #7490, #7492, #7644 | -| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | -| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #7794, #7804, #7810, #7813, #7816, #7891, #8050 | -| [@apoapostolov](https://github.com/apoapostolov) | #8127 | -| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | -| [@Arul-](https://github.com/Arul-) | #7878 | -| [@backryun](https://github.com/backryun) | #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230 | -| [@c4usal](https://github.com/c4usal) | #8129 | -| [@Capslockb](https://github.com/Capslockb) | #7892 | -| [@Chewji9875](https://github.com/Chewji9875) | #7545 | -| [@chirag127](https://github.com/chirag127) | #7520, #8143 | -| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | -| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | -| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | -| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | -| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | -| [@ekinnee](https://github.com/ekinnee) | #7613, #7614, #7662, #7779, #7927, #7932, #7980 | -| [@enjoyer-hub](https://github.com/enjoyer-hub) | #7863 | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | -| [@FenjuFu](https://github.com/FenjuFu) | #7942 | -| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | -| [@growab](https://github.com/growab) | #7062 | -| [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | -| [@HassiyYT](https://github.com/HassiyYT) | #7864 | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973 | -| [@hppsc1215](https://github.com/hppsc1215) | #7546 | -| [@huohua-dev](https://github.com/huohua-dev) | #6794 | -| [@hydraxman](https://github.com/hydraxman) | #7909 | -| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | -| [@irvandikky](https://github.com/irvandikky) | #7695 | -| [@isiahw1](https://github.com/isiahw1) | #7555 | -| [@JxnLexn](https://github.com/JxnLexn) | #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | -| [@KooshaPari](https://github.com/KooshaPari) | #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | -| [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | -| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | -| [@loulanyue](https://github.com/loulanyue) | #7540 | -| [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | -| [@megamen32](https://github.com/megamen32) | #7313 | -| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | -| [@mikolaj92](https://github.com/mikolaj92) | #6973 | -| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | -| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | -| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | -| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8233 | -| [@not-knope](https://github.com/not-knope) | #8206 | -| [@nramabad](https://github.com/nramabad) | #7926 | -| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | -| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8220 | -| [@rafaumeu](https://github.com/rafaumeu) | #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | -| [@rushsinging](https://github.com/rushsinging) | #7256 | -| [@seanford](https://github.com/seanford) | #8218, #8232 | -| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | -| [@Securiteru](https://github.com/Securiteru) | #7683 | -| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | -| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | -| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | -| [@tianrking](https://github.com/tianrking) | #7353 | -| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | -| [@tmone](https://github.com/tmone) | #7806, #7933 | -| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #8128 | -| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | -| [@vzts](https://github.com/vzts) | #7390 | -| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | -| [@Wibias](https://github.com/Wibias) | #7125 | -| [@Witroch4](https://github.com/Witroch4) | #7901, #7902 | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | -| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | -| [@xz-dev](https://github.com/xz-dev) | #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | -| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | --- diff --git a/docs/i18n/pt-BR/CHANGELOG.md b/docs/i18n/pt-BR/CHANGELOG.md index 5728cb8ee5..83595783df 100644 --- a/docs/i18n/pt-BR/CHANGELOG.md +++ b/docs/i18n/pt-BR/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/ro/CHANGELOG.md b/docs/i18n/ro/CHANGELOG.md index f1ef3329d1..833db87086 100644 --- a/docs/i18n/ro/CHANGELOG.md +++ b/docs/i18n/ro/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/sk/CHANGELOG.md b/docs/i18n/sk/CHANGELOG.md index 2d7a53e258..2794b3c37b 100644 --- a/docs/i18n/sk/CHANGELOG.md +++ b/docs/i18n/sk/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/sw/CHANGELOG.md b/docs/i18n/sw/CHANGELOG.md index 94c5b05a79..c85b0a19a0 100644 --- a/docs/i18n/sw/CHANGELOG.md +++ b/docs/i18n/sw/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/te/CHANGELOG.md b/docs/i18n/te/CHANGELOG.md index 1e187b92b9..4657aec762 100644 --- a/docs/i18n/te/CHANGELOG.md +++ b/docs/i18n/te/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/tr/CHANGELOG.md b/docs/i18n/tr/CHANGELOG.md index c4226be42a..9a814852f8 100644 --- a/docs/i18n/tr/CHANGELOG.md +++ b/docs/i18n/tr/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/ur/CHANGELOG.md b/docs/i18n/ur/CHANGELOG.md index c640549db7..c2be38c2e3 100644 --- a/docs/i18n/ur/CHANGELOG.md +++ b/docs/i18n/ur/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13 diff --git a/docs/i18n/zh-CN/CHANGELOG.md b/docs/i18n/zh-CN/CHANGELOG.md index 7d70f1a7c0..ca02f38a92 100644 --- a/docs/i18n/zh-CN/CHANGELOG.md +++ b/docs/i18n/zh-CN/CHANGELOG.md @@ -8,6 +8,1376 @@ ## [3.8.49] — TBD +_Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ + +### ✨ New Features + +- **feat:** generalize ensureThinkingBudget to all providers + preserve server-side tool invocations on antigravity ([#6979](https://github.com/diegosouzapw/OmniRoute/pull/6979)) — thanks @rafaumeu +- **feat(6922):** effort-tier aliases for glm-5.2 & mimo-v2.5 on opencode-go ([#6987](https://github.com/diegosouzapw/OmniRoute/pull/6987)) — thanks @rafaumeu +- **feat(providers):** curated OpenRouter embeddings catalog + specialty merge in live discovery (#6976) ([#6994](https://github.com/diegosouzapw/OmniRoute/pull/6994)) +- **feat(quota):** opt-in auto-ping to keep Codex quota windows warm (#6977) ([#6995](https://github.com/diegosouzapw/OmniRoute/pull/6995)) +- **feat(providers):** add Agnes AI native provider support ([#7035](https://github.com/diegosouzapw/OmniRoute/pull/7035)) — thanks @HouMinXi +- **feat(sse):** allow disabling `:` comment heartbeats via OMNIROUTE_SSE_COMMENTS=off ([#7036](https://github.com/diegosouzapw/OmniRoute/pull/7036)) — thanks @xier2012 +- **feat(perf):** add performance.mark/measure to SSE pipeline + request-size metric ([#7045](https://github.com/diegosouzapw/OmniRoute/pull/7045)) — thanks @oyi77 +- **feat(providers):** add Dahl free inference provider ([#7062](https://github.com/diegosouzapw/OmniRoute/pull/7062)) — thanks @growab +- **feat(ci):** boot-smoke the packed npm tarball (check:pack-boot, #7065 class killer) ([#7086](https://github.com/diegosouzapw/OmniRoute/pull/7086)) +- **feat(ci):** hotfix fast-lane + tests-only E2E skip (WS3.1) ([#7088](https://github.com/diegosouzapw/OmniRoute/pull/7088)) +- **feat(ci):** continuous release-green — on-push quick gate + 3x/day full sweep (WS5.1) ([#7089](https://github.com/diegosouzapw/OmniRoute/pull/7089)) +- **feat(ci):** duration-balanced E2E shards via LPT bin-packing (WS4.1) ([#7090](https://github.com/diegosouzapw/OmniRoute/pull/7090)) +- **feat(ci):** TypeScript 7 native shadow for typecheck:core (WS4.2, advisory) ([#7091](https://github.com/diegosouzapw/OmniRoute/pull/7091)) +- **feat(release):** npm staged publishing + pre-publish boot-smoke (WS1.3) ([#7092](https://github.com/diegosouzapw/OmniRoute/pull/7092)) +- **feat(release):** post-publish verifier — clean-container install + boot (WS1.4) ([#7109](https://github.com/diegosouzapw/OmniRoute/pull/7109)) +- **feat(ci):** Mergify merge queue + manual-train fallback runbook (WS3.4/WS3.2) ([#7112](https://github.com/diegosouzapw/OmniRoute/pull/7112)) +- **feat(ci):** Windows leg for Electron prepare smoke (WS1.5) ([#7113](https://github.com/diegosouzapw/OmniRoute/pull/7113)) +- **feat(ci):** Codecov patch coverage (informational) + fix missing lcov reporter (WS5.6) ([#7114](https://github.com/diegosouzapw/OmniRoute/pull/7114)) +- **feat(sidecar):** support conditional provider manifest refresh ([#7130](https://github.com/diegosouzapw/OmniRoute/pull/7130)) — thanks @KooshaPari +- **feat(homolog):** real-environment E2E homologation suite (npm run homolog) ([#7133](https://github.com/diegosouzapw/OmniRoute/pull/7133)) +- **feat(usage):** add Codex reset credit picker ([#7154](https://github.com/diegosouzapw/OmniRoute/pull/7154)) — thanks @JxnLexn +- **feat(ci):** Trunk Flaky Tests uploads for vitest + Playwright E2E (WS5.2/5.3) ([#7175](https://github.com/diegosouzapw/OmniRoute/pull/7175)) +- **feat(ci):** Trunk Flaky Tests upload on the fast-path vitest job (per-PR volume) ([#7205](https://github.com/diegosouzapw/OmniRoute/pull/7205)) +- **feat(kiro):** register GPT-5.6 Sol/Terra/Luna model family ([#7209](https://github.com/diegosouzapw/OmniRoute/pull/7209)) +- **feat(dashboard):** show Codex plan label in provider and quota views ([#7210](https://github.com/diegosouzapw/OmniRoute/pull/7210)) +- **feat(dashboard):** add reorder connections by availability button ([#7211](https://github.com/diegosouzapw/OmniRoute/pull/7211)) +- **feat(dashboard):** add 180D and 365D usage/cost analytics periods (#7213) ([#7213](https://github.com/diegosouzapw/OmniRoute/pull/7213)) +- **feat(api):** add Vary: Accept-Encoding to token-authenticated /v1* responses (#6737) ([#7217](https://github.com/diegosouzapw/OmniRoute/pull/7217)) +- **feat(api):** expose GET /api/usage/model-latency-stats (#6873) ([#7218](https://github.com/diegosouzapw/OmniRoute/pull/7218)) +- **feat(dashboard):** add compression-mode selector to Context & Cache combos page (#6760) ([#7219](https://github.com/diegosouzapw/OmniRoute/pull/7219)) +- **feat(sse):** route GitHub Copilot Claude models through native /v1/messages ([#7223](https://github.com/diegosouzapw/OmniRoute/pull/7223)) +- **feat(mitm):** add Antigravity reasoning-effort overrides ([#7228](https://github.com/diegosouzapw/OmniRoute/pull/7228)) +- **feat:** replace free-text model inputs with hidePaid-aware Selects (#6540) ([#7229](https://github.com/diegosouzapw/OmniRoute/pull/7229)) +- **feat:** editable ComfyUI base-URL field + per-connection override for image/video/music generation (#6928) ([#7232](https://github.com/diegosouzapw/OmniRoute/pull/7232)) +- **feat(sse):** add optional-enum null-omission idiom for codex strict-mode tools (#7023) ([#7233](https://github.com/diegosouzapw/OmniRoute/pull/7233)) +- **feat(sse):** preserve tools/tool_choice for tool-bearing requests through fusion combos (#6771) ([#7235](https://github.com/diegosouzapw/OmniRoute/pull/7235)) +- **feat(api):** accept x-goog-api-key header for client-facing auth (#7034) ([#7236](https://github.com/diegosouzapw/OmniRoute/pull/7236)) +- **feat(sse):** add native xAI Grok Imagine video generation provider ([#7238](https://github.com/diegosouzapw/OmniRoute/pull/7238)) +- **feat:** add Type filter and easiest-first sort to Free Provider Rankings (#6915) ([#7240](https://github.com/diegosouzapw/OmniRoute/pull/7240)) +- **feat(cli):** add Grok Build CLI tool setup (~/.grok/config.toml) ([#7241](https://github.com/diegosouzapw/OmniRoute/pull/7241)) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway ([#7246](https://github.com/diegosouzapw/OmniRoute/pull/7246)) +- **feat(providers):** let custom connections opt into prompt-cache capability (#6880) ([#7257](https://github.com/diegosouzapw/OmniRoute/pull/7257)) +- **feat(db):** include xp_audit_log in automatic retention/prune (#6801) ([#7260](https://github.com/diegosouzapw/OmniRoute/pull/7260)) +- **feat(api):** structured X-Routing-Fallback-Reason header for relay routing (#6872) ([#7262](https://github.com/diegosouzapw/OmniRoute/pull/7262)) +- **feat(compression):** support RTK TOML schema v1 filters ([#7281](https://github.com/diegosouzapw/OmniRoute/pull/7281)) — thanks @JxnLexn +- **feat:** add principal-scoped CCR MCP lifecycle ([#7282](https://github.com/diegosouzapw/OmniRoute/pull/7282)) — thanks @JxnLexn +- **feat(morph):** refresh curated models ([#7314](https://github.com/diegosouzapw/OmniRoute/pull/7314)) — thanks @backryun +- **feat(issue-agent):** surface RecordedTriageTimeoutError as 504 ([#7315](https://github.com/diegosouzapw/OmniRoute/pull/7315)) — thanks @KooshaPari +- **feat(incident-response):** structured incident response templates ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **feat(providers):** add xAI OAuth PKCE provider ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(models):** advertise Claude reasoning-effort variants in /v1/models ([#7497](https://github.com/diegosouzapw/OmniRoute/pull/7497)) — thanks @thepigdestroyer +- **feat(kimi):** sync Code, Web, and Moonshot providers ([#7531](https://github.com/diegosouzapw/OmniRoute/pull/7531)) — thanks @backryun +- **feat(resilience):** guard OmniRoute peer routing loops ([#7555](https://github.com/diegosouzapw/OmniRoute/pull/7555)) — thanks @isiahw1 +- **feat:** add Mixedbread AI as embeddings provider (#6660) ([#7595](https://github.com/diegosouzapw/OmniRoute/pull/7595)) +- **feat(providers):** add Rev AI speech-to-text provider (#6655) ([#7596](https://github.com/diegosouzapw/OmniRoute/pull/7596)) +- **feat:** add Freepik (Magnific Mystic) image generation provider (#6654) ([#7597](https://github.com/diegosouzapw/OmniRoute/pull/7597)) +- **feat(sse):** add DeepInfra as a video-generation provider (#6653) ([#7598](https://github.com/diegosouzapw/OmniRoute/pull/7598)) +- **feat(providers):** add Felo chat-aggregator provider (#6666) ([#7599](https://github.com/diegosouzapw/OmniRoute/pull/7599)) +- **feat(sse):** add Notion AI Web (Unofficial/Experimental) provider (#6758) ([#7600](https://github.com/diegosouzapw/OmniRoute/pull/7600)) +- **feat:** add FreeTheAi as OpenAI-compatible gateway provider (#6670) ([#7602](https://github.com/diegosouzapw/OmniRoute/pull/7602)) +- **feat:** add Gladia as an async speech-to-text provider (#6657) ([#7603](https://github.com/diegosouzapw/OmniRoute/pull/7603)) +- **feat:** add EdgeTTS audio-tts provider (#6668) ([#7605](https://github.com/diegosouzapw/OmniRoute/pull/7605)) +- **feat(video):** add Novita AI as video-generation provider (#6658) ([#7606](https://github.com/diegosouzapw/OmniRoute/pull/7606)) +- **feat:** add Segmind image+video provider (#6656) ([#7608](https://github.com/diegosouzapw/OmniRoute/pull/7608)) +- **feat:** add Microsoft Designer as image provider (#6672) ([#7609](https://github.com/diegosouzapw/OmniRoute/pull/7609)) +- **feat:** per-model default reasoning_effort + no-think none on OpenAI path (#6879) ([#7631](https://github.com/diegosouzapw/OmniRoute/pull/7631)) +- **feat(sse):** per-model upstream header-response timeout override (#6354) ([#7632](https://github.com/diegosouzapw/OmniRoute/pull/7632)) +- **feat(dashboard):** in-product guidance for prompt compression engines (#7530) ([#7634](https://github.com/diegosouzapw/OmniRoute/pull/7634)) +- **feat(usage):** add TTFT/E2E-latency/tokens-per-second to model latency stats (#6875) ([#7635](https://github.com/diegosouzapw/OmniRoute/pull/7635)) +- **feat:** import providers from CSV/JSON file (#6836) ([#7636](https://github.com/diegosouzapw/OmniRoute/pull/7636)) +- **feat:** confirm before removing a single connection (#7361) ([#7640](https://github.com/diegosouzapw/OmniRoute/pull/7640)) +- **feat(sse):** honor excluded models in no-auth auto-combo candidate pool (#7622) ([#7646](https://github.com/diegosouzapw/OmniRoute/pull/7646)) +- **feat(providers):** add g4f.space no-key gateway (groq/gemini/pollinations/ollama/nvidia) (#6650) ([#7647](https://github.com/diegosouzapw/OmniRoute/pull/7647)) +- **feat:** rate-limit queue admission control (maxQueueDepth + 15s default) (#6593) ([#7649](https://github.com/diegosouzapw/OmniRoute/pull/7649)) +- **feat(sse):** generalize session affinity TTL to all providers (#7274) ([#7650](https://github.com/diegosouzapw/OmniRoute/pull/7650)) +- **feat:** OpenRouter quota tracking (key/credits + free-window counter) (#6842) ([#7651](https://github.com/diegosouzapw/OmniRoute/pull/7651)) +- **feat(sse):** quota tracking for AgentRouter, v0 (Vercel), FreeModel (#6850, #6845, #7075) ([#7653](https://github.com/diegosouzapw/OmniRoute/pull/7653)) +- **feat(providers):** Speechmatics STT, gTTS, VibeProxy preset (#6659, #6667, #6874) ([#7655](https://github.com/diegosouzapw/OmniRoute/pull/7655)) +- **feat(api):** route Google AI Studio Imagen through /v1/images/generations ([#7656](https://github.com/diegosouzapw/OmniRoute/pull/7656)) — thanks @danscMax + +- **feat(auth):** OIDC as optional dashboard admin login gate (password fallback preserved) ([#6973](https://github.com/diegosouzapw/OmniRoute/pull/6973)) — thanks @mikolaj92 +- **feat(api):** add pagination params to 8 DB modules + recharts code-split ([#7046](https://github.com/diegosouzapw/OmniRoute/pull/7046)) — thanks @oyi77 +- **feat(proxy):** operator-level proxy subscriptions (Karing-style) — hardened, ready for review ([#7299](https://github.com/diegosouzapw/OmniRoute/pull/7299)) — thanks @xier2012 +- **feat(grok-cli):** align with official Grok Build client ([#7358](https://github.com/diegosouzapw/OmniRoute/pull/7358)) — thanks @backryun +- **feat(providers):** Complete GHE Copilot OAuth provider implementation ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) — thanks @hppsc1215 +- **feat(guardrails):** add CredentialMaskerGuardrail for API key/secret redaction ([#7683](https://github.com/diegosouzapw/OmniRoute/pull/7683)) — thanks @Securiteru +- **feat(perplexity):** refresh provider integrations ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- **feat(providers):** notion-web live model discovery via getAvailableModels ([#7696](https://github.com/diegosouzapw/OmniRoute/pull/7696)) — thanks @artickc +- **feat(providers):** add proactive cf_clearance/User-Agent hint to grok-web connection dialog (#7567) ([#7713](https://github.com/diegosouzapw/OmniRoute/pull/7713)) +- **feat:** add live gRPC-web quota fetcher for grok-cli (#6844) ([#7714](https://github.com/diegosouzapw/OmniRoute/pull/7714)) +- **feat(api):** add opt-in auto-sync scheduler for free-proxy sources (#7079) ([#7716](https://github.com/diegosouzapw/OmniRoute/pull/7716)) +- **feat(dashboard):** show proxy name in badge, sort saved-proxy picker, default to Saved tab (#7643) ([#7720](https://github.com/diegosouzapw/OmniRoute/pull/7720)) +- **feat(cli):** add auth export command for decrypted provider credentials (#6683) ([#7724](https://github.com/diegosouzapw/OmniRoute/pull/7724)) +- **feat(oauth):** accept full ChatGPT session JSON for Codex manual import (#6636) ([#7725](https://github.com/diegosouzapw/OmniRoute/pull/7725)) +- **feat(sse):** add nvidia NIM local RPM budget + concurrency cap (#6846) ([#7726](https://github.com/diegosouzapw/OmniRoute/pull/7726)) +- **feat(gemini-web):** emulate OpenAI tool calling via the webTools prompt shim (#7286) ([#7727](https://github.com/diegosouzapw/OmniRoute/pull/7727)) +- **feat(services):** introduce pluggable service-provider contract, migrate 9router (#7333) ([#7730](https://github.com/diegosouzapw/OmniRoute/pull/7730)) +- **feat(mitm):** root-CA + per-host leaf certs for AgentBridge static server (#6684) ([#7731](https://github.com/diegosouzapw/OmniRoute/pull/7731)) +- **feat(providers):** add hailuo-web (MiniMax web) chat provider (#6673) ([#7734](https://github.com/diegosouzapw/OmniRoute/pull/7734)) +- **feat:** browser login for Grok Build provider (#7013) ([#7735](https://github.com/diegosouzapw/OmniRoute/pull/7735)) +- **feat(routing):** wire interceptFetch tool interception into the chat pipeline (#7339) ([#7736](https://github.com/diegosouzapw/OmniRoute/pull/7736)) +- **feat(sse):** add X-OmniRoute-Decision routing trace header (#6022) ([#7765](https://github.com/diegosouzapw/OmniRoute/pull/7765)) +- **feat(providers):** zai-web live model discovery with local-catalog fallback (#7678) ([#7766](https://github.com/diegosouzapw/OmniRoute/pull/7766)) +- **feat(api):** sync upstream reasoning.supported_efforts into synced-model catalog (#7694) ([#7767](https://github.com/diegosouzapw/OmniRoute/pull/7767)) +- **feat(dashboard):** pin Kimi providers first in category + official supporter card accent ([#7775](https://github.com/diegosouzapw/OmniRoute/pull/7775)) +- **feat(chaos+ponytail):** parallel chaos-mode dispatch + ponytail output … ([#7781](https://github.com/diegosouzapw/OmniRoute/pull/7781)) — thanks @Moseyuh333 +- **feat(perf):** IC2 — cache provider connections by ID + lazy-decrypt credentials ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)) — thanks @oyi77 +- **feat(quality):** gate the free-tier headline so it can never silently drift again ([#7798](https://github.com/diegosouzapw/OmniRoute/pull/7798)) +- **feat(providers):** expose an explicit tier override for any provider connection (#7818) ([#7838](https://github.com/diegosouzapw/OmniRoute/pull/7838)) +- **feat(routing):** read-only auto/* candidate transparency + per-API-key exclusions (#7819) ([#7839](https://github.com/diegosouzapw/OmniRoute/pull/7839)) +- **feat(catalog):** map unmapped free tiers, add navy + aihorde, surface keyless providers ([#7840](https://github.com/diegosouzapw/OmniRoute/pull/7840)) +- **feat(providers):** add OpenRouter speech-to-text (audio transcription) provider ([#7861](https://github.com/diegosouzapw/OmniRoute/pull/7861)) — thanks @Tasogarre +- **feat(qwen):** add Qwen3.8 Max Preview catalogs [Part 2/3] ([#7874](https://github.com/diegosouzapw/OmniRoute/pull/7874)) — thanks @backryun +- **feat:** support Bun bundled SQLite runtime ([#7878](https://github.com/diegosouzapw/OmniRoute/pull/7878)) — thanks @Arul- +- **feat(providers):** add 5 free-tier providers (ainative, aion, sealion, routeway, nara) ([#7887](https://github.com/diegosouzapw/OmniRoute/pull/7887)) +- **feat(vnc-session):** persistent noVNC browser login for web-cookie providers ([#7892](https://github.com/diegosouzapw/OmniRoute/pull/7892)) — thanks @Capslockb +- **feat(sse):** add PromptQL playground provider (unofficial) ([#7911](https://github.com/diegosouzapw/OmniRoute/pull/7911)) — thanks @artickc +- **feat(cline):** align ClinePass catalog and request protocol ([#7914](https://github.com/diegosouzapw/OmniRoute/pull/7914)) — thanks @backryun +- **feat:** narrow mcp:connect scope + per-key HTTP tool-scope binding (#7895) ([#7967](https://github.com/diegosouzapw/OmniRoute/pull/7967)) +- **feat:** provider tab account search + mirrored top pagination (#7937) ([#7968](https://github.com/diegosouzapw/OmniRoute/pull/7968)) +- **feat:** canonical numeric helpers + tier-1 (analytics) migration (#7879) ([#7969](https://github.com/diegosouzapw/OmniRoute/pull/7969)) +- **feat(sse):** add HyperAgent (hyperagent.com) unofficial web provider ([#7994](https://github.com/diegosouzapw/OmniRoute/pull/7994)) — thanks @artickc +- **feat:** copilot-m365-web tone-selected model variants (#7872) ([#7997](https://github.com/diegosouzapw/OmniRoute/pull/7997)) +- **feat(media):** Adobe Firefly image + video generation provider ([#8006](https://github.com/diegosouzapw/OmniRoute/pull/8006)) — thanks @artickc +- **feat(routing):** add prompt-cache affinity ([#8008](https://github.com/diegosouzapw/OmniRoute/pull/8008)) — thanks @JxnLexn +- **feat(compression):** select model-aware tokenizers ([#8009](https://github.com/diegosouzapw/OmniRoute/pull/8009)) — thanks @JxnLexn +- **feat(compression):** add Responses tool-output engine ([#8010](https://github.com/diegosouzapw/OmniRoute/pull/8010)) — thanks @JxnLexn +- **feat(dashboard):** Kimi sponsor banner, Kimi Coding preset, official logomarks and partner links ([#8039](https://github.com/diegosouzapw/OmniRoute/pull/8039)) +- **feat(dashboard):** make Codex quota card windows reflect reality ([#8054](https://github.com/diegosouzapw/OmniRoute/pull/8054)) — thanks @insoln +- **feat(compression):** teach the model the CCR retrieve protocol on first marker (#8033) ([#8063](https://github.com/diegosouzapw/OmniRoute/pull/8063)) +- **feat(compression):** per-model/endpoint compression exclusion filter (#8034) ([#8064](https://github.com/diegosouzapw/OmniRoute/pull/8064)) +- **feat(providers):** add CLOVA Studio, InternLM and Ant Ling API-key providers ([#8077](https://github.com/diegosouzapw/OmniRoute/pull/8077)) — thanks @alvaretto +- **feat(codex):** support reference image edits ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- **feat(providers):** add weekly quota tracking for grok-web ([#8127](https://github.com/diegosouzapw/OmniRoute/pull/8127)) — thanks @apoapostolov +- **feat(providers):** add Sarvam AI, Writer Palmyra and PLaMo API-key providers ([#8161](https://github.com/diegosouzapw/OmniRoute/pull/8161)) — thanks @alvaretto +- **feat:** native Fish Audio TTS provider on /v1/audio/speech (#8099) ([#8164](https://github.com/diegosouzapw/OmniRoute/pull/8164)) +- **feat:** zh-CN terminology glossary + consistency gate + normalization pass (#8038) ([#8166](https://github.com/diegosouzapw/OmniRoute/pull/8166)) +- **feat(providers):** add Typhoon (Thailand) and Inception Mercury diffusion LLM ([#8170](https://github.com/diegosouzapw/OmniRoute/pull/8170)) — thanks @alvaretto +- **feat(sse):** restrict auto-combo no-auth pool to allowlist (opencode, felo) + docs ([#8183](https://github.com/diegosouzapw/OmniRoute/pull/8183)) +- **feat(sre):** add tcp-close-analyzer.py for debugging client-vs-server TCP close order ([#8208](https://github.com/diegosouzapw/OmniRoute/pull/8208)) — thanks @hartmark +- **feat(settings):** configurable model catalog cache TTL ([#8219](https://github.com/diegosouzapw/OmniRoute/pull/8219)) — thanks @oyi77 +- **feat(github-models):** refresh catalog and compatibility ([#8225](https://github.com/diegosouzapw/OmniRoute/pull/8225)) — thanks @backryun +- **feat(github):** refresh Copilot model catalog ([#8226](https://github.com/diegosouzapw/OmniRoute/pull/8226)) — thanks @backryun +- **feat:** classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) ([#8241](https://github.com/diegosouzapw/OmniRoute/pull/8241)) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- **feat(sse):** every completion response now carries an `X-OmniRoute-Decision: strategy=; provider=; latency_ms=` header exposing the routing decision — `` is the combo strategy (`priority`, `weighted`, `fusion`, etc.) or `single` for a non-combo request — for client-side debugging/analytics without server log access (#6022 — thanks @chirag127). +- **feat(ws):** the live-dashboard WebSocket server now auto-starts in-process (via `instrumentation-node.ts`) across every deployment mode — dev, production, Docker, Electron — with no separate sidecar script; the default WS port moved from 20129 to **20132** to avoid colliding with `API_PORT` in split-port setups, the deprecated `OMNIROUTE_DISABLE_LIVE_WS` env was consolidated into `OMNIROUTE_ENABLE_LIVE_WS` (default enabled), and the WS path is now derived from `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL`'s pathname (`/live-ws` fallback) (#6072 — thanks @ianriizky). +- feat(sse): configurable per-model upstream header-response timeout override, precedence model > provider > global; applied to codex reasoning-heavy tiers (gpt-5.5-high/xhigh, gpt-5.6-\*-high/xhigh) (#6354) +- **feat(dashboard):** Replace free-text model inputs in the Routing (web search route), Combo Defaults (handoff model), and Background Degradation tabs with a `hidePaidModels`-aware `ModelSelectField`, add a fail-open "paid-only pattern" warning to the per-model routing rule pattern field, and reject paid-only model targets at save time on `PATCH /api/settings`, `PATCH /api/settings/combo-defaults`, and `PUT /api/settings/background-degradation` when `hidePaidModels` is on ([#6540](https://github.com/diegosouzapw/OmniRoute/issues/6540)) +- **feat(compression):** new **omniglyph** engine (context-as-image) — renders system prompt, tool docs, and dense history as compact PNG pages the model reads instead of text (~10× fewer tokens on the converted block; 59–70% end-to-end measured). Works stacked with RTK/Caveman (`stackPriority: 90`) or standalone (`mode: omniglyph`); restricted to Claude Fable 5 over the direct Anthropic route, fail-closed gates with `skip:` techniques, preview (`stable: false`, off by default) (#6556). Dependency bumped to `omniglyph@^1.0.2` for upstream ReDoS fixes (#6661). +- **feat(sse):** rate-limit request queue admission control — `resilienceSettings.requestQueue.maxQueueDepth` (default `0` = disabled, opt-in 0–100000) fast-rejects a request with a typed `RATE_LIMIT_QUEUE_FULL` error once the local per-provider+connection queue already holds `maxQueueDepth` requests, instead of growing the queue unboundedly; the factory default for `requestQueue.maxWaitMs` (how long a request may wait before being dropped) also fell from 120s to 15s so a saturated queue fails fast (#6593 — thanks @chirag127). +- **feat(sandbox):** the skill sandbox gained a container-provider abstraction that auto-detects and uses the best native runtime per host — Apple Container (macOS 26+), WSL container (`wslc.exe`), OrbStack, Podman — instead of hardcoding `docker run`, removing the Docker Desktop requirement on macOS/Windows (#6611 — thanks @KooshaPari). +- feat(oauth): accept the full ChatGPT session JSON (not just a bare access token) when pasting Codex credentials manually or via `POST /api/oauth/codex/import-token` (#6636) +- feat(sse): add 5 no-key g4f.space gateway providers — `g4f-groq`, `g4f-gemini`, `g4f-pollinations`, `g4f-ollama`, `g4f-nvidia` — a free, no-signup reverse proxy (gpt4free project) fronting Groq, Gemini, Pollinations, Ollama, and NVIDIA NIM, rate-limited to 5 req/min per IP (#6650 — thanks @chirag127). +- feat(sse): add DeepInfra as a video-generation provider via its native synchronous inference endpoint (#6653) +- feat(providers): add Freepik (Magnific Mystic) API-key image generation provider — async submit/poll flow with realism/fluid/zen/flexible/super_real/editorial_portraits models (#6654) +- feat(providers): add Rev AI speech-to-text provider with async job upload/poll/transcript flow (#6655) +- **feat(providers):** add **Segmind** as an image + video generation provider — `x-api-key` auth against `POST https://api.segmind.com/v1/{model}`, with a curated starter model list (Flux, Stable Diffusion XL/3.5, Kandinsky for image; Wan, Hunyuan, LTX, Kling for video) (#6656). +- feat(providers): add Gladia as an async speech-to-text provider (#6657) +- feat(video): add Novita AI as a video-generation provider (Wan/Kling async submit-poll) (#6658) +- **feat(providers):** add Speechmatics as an STT provider — async batch transcription (Enhanced operating point), 8 hours/month free tier, no credit card required. Streaming (real-time) mode is out of scope for v1. (#6659) +- feat(providers): add Mixedbread AI as an embeddings provider (`mxbai-embed-large-v1`, `mxbai-embed-2d-large-v1`, free tier) (#6660) +- **feat(providers):** add Felo (felo.ai) as a free, no-signup, no-API-key chat/search-agent aggregator provider (`felo-web`) — joins the existing `-web` family (DuckDuckGo AI Chat, Blackbox, etc). Five models (`felo-chat`, `felo-search`, `felo-scholar`, `felo-social`, `felo-document`) map to Felo's search categories; the executor opens a search thread then translates Felo's bespoke SSE stream into OpenAI-compatible chunks (#6666). +- **feat(providers):** add gTTS (Google Translate TTS) as a free, no-signup audio-speech provider — routes through Google's current `batchexecute` RPC endpoint (the previously proposed `translate_tts` endpoint is deprecated), splitting input at the 100-char-per-request limit. (#6667) +- **feat(sse):** add EdgeTTS (Microsoft Edge "Read Aloud") as a free, no-API-key `audio-tts` provider — the first WebSocket-transport speech provider, with per-client-IP rate limiting. (#6668) +- feat(providers): add FreeTheAi as an OpenAI-compatible gateway provider with a free Discord-signup tier (#6670) +- feat(sse): add Microsoft Designer as an unofficial web-session image provider, reverse-engineered submit-then-poll DallE.ashx flow (#6672) +- **feat(providers):** add Hailuo Web (`hailuo-web`) — a free, `_token`-based web-cookie chat provider for the MiniMax consumer chat product at hailuo.ai, ported from the g4f reference implementation (MD5-chain request signing, custom `event:`/`data:` SSE parsing). Distinct from the existing paid API-key `minimax`/`minimax-cn` providers. (#6673) +- **feat(cli):** new `omniroute auth export` command dumps DECRYPTED provider credentials (`apiKey`/`accessToken`/`refreshToken`/`idToken`) for one connection (`--id `) or all connections, as `json` or `env` (`--format`), local-only and gated behind `--force` — no DB access happens without it, a stderr warning banner prints before any plaintext, `--out ` writes with `0600` permissions, and per-field decrypt failures surface as a `DecryptFailed` boolean instead of aborting the export or leaking the caught error text (#6683) +- **feat(mitm):** the AgentBridge static MITM server (`server.cjs`) can now issue a per-host TLS leaf from a persisted local root CA (`src/mitm/cert/rootCa.ts`, reusing the CA/leaf crypto already proven for TPROXY in `tproxy/dynamicCert.ts`) instead of a single static self-signed leaf scoped only to the 4 antigravity hosts — a fresh install covers the full `MITM_TOOL_HOSTS` set automatically; an install that already trusted the old leaf keeps using it until the operator opts in via `MITM_ROOT_CA_ENABLED=true` (`src/mitm/cert/migration.ts`), so no existing install is silently upgraded to the more powerful any-host-signing CA trust model (#6684). +- **fix(sse):** skip `thinkingConfig` for Gemma models on the OpenAI→Gemini path so OpenAI-shape clients no longer get a 400 from Vertex. (thanks @chy1211) +- **feat(xai):** route xAI clients to Grok's native `/v1/responses` endpoint instead of the chat-completions bridge. (thanks @ryanngit) +- **feat(models):** add a Settings → AI "Model Overrides" UI plus `/api/model-capability-overrides` CRUD and a `model_capability_overrides` table, letting operators set a manual max-output-token override per provider/model (#6727 — thanks @xz-dev). +- **feat(api):** add `Vary: Accept-Encoding` to token-authenticated `/v1*`/`/v1beta*` responses so downstream caches distinguish compressed vs uncompressed variants (RFC 9110 §12.5.5). (thanks @chirag127) +- feat(sse): add Notion AI Web (Unofficial/Experimental) cookie-session provider (#6758) +- **feat(dashboard):** add per-routing-combo compression-mode override to the Compression Combos page under Context & Cache, alongside the existing combo-card quick override. (#6760) +- **feat(resilience):** operator-configurable account rotation policy — a new `rotationConfig` layer lets operators tune how connections rotate on failure, wired into `accountFallback` (#6763 — thanks @artickc). +- **feat(sse):** preserve `tools`/`tool_choice` for tool-bearing requests through fusion combos — bypass panel synthesis and route straight to the judge with tools intact (#6771 — thanks @chirag127). +- **chore(cursor): add Grok 4.5 effort/fast model IDs** (#6774 — thanks @andrewmunsell). +- **feat(codex):** Codex provider model discovery now fetches the live catalog from `chatgpt.com/backend-api/codex/models` using Codex-shaped headers, falling back to a GitHub-hosted model manifest and then to the local static catalog when the live/GitHub sources are unavailable or return an unexpected shape — new `src/app/api/providers/[id]/models/discovery/codex.ts` (normalization, version-gating, merge/enrich against the local catalog) covered by `tests/unit/provider-models-discovery-split.test.ts` and `tests/unit/provider-models-route-codex.test.ts` (#6776 — thanks @JxnLexn). +- **feat(cursor):** register the Opus 4.8, Fable 5, and Sonnet 5 model families for the Cursor Agent provider so the latest Claude/Fable model ids route correctly (#6779 — thanks @andrewmunsell). +- **Changelog fragments (`changelog.d/`)**: PRs now add their changelog entry as a new fragment file (`changelog.d/{features|fixes|maintenance}/-.md`) instead of editing `CHANGELOG.md` — two PRs never touch the same file, structurally eliminating the CHANGELOG-eat merge conflicts that forced a re-sync push + full CI re-run after every sibling merge (O(N²) CI runs in a merge-storm). `scripts/release/aggregate-changelog.mjs` (npm run changelog:aggregate) folds fragments into the living section at release reconciliation, and `check:changelog-integrity` now also validates fragment well-formedness. Regression guard: `tests/unit/changelog-fragments.test.ts`. +- **feat(proxy):** add a latency-optimized proxy rotation strategy that ranks pool entries by measured round-trip latency, extending the existing round-robin/random/sticky proxy-pool selection (#6798 — thanks @iamraydoan). +- feat(db): include `xp_audit_log` in the automatic retention/prune cycle, with a configurable `retention.xpAuditLog` setting (#6801) +- **feat(fusion):** the fusion judge may now draw on its own knowledge and override the panel when every panel answer is wrong or incomplete, instead of being restricted to synthesizing only from panel output (#6804 — thanks @chirag127). +- **feat(dashboard):** search box on the Playground's raw model `` (#4086) — the shared `ModelSelectModal` (combo builder + CLI-code cards) already had search, but Playground's `StudioConfigPane` model dropdown stayed a flat unsearchable list, unusable once a provider like OpenRouter contributed 50+ models. Typing now filters the dropdown (Turkish-safe accent/case-insensitive match via `matchesSearch`), while the currently selected model always stays pinned in the list even if it no longer matches the query, so typing never silently swaps the active selection. Reuses the existing `common.search` i18n key (already translated in all 42 locales) — no new translation key needed. Regression guard: `tests/unit/playground-model-selection-3731.test.ts` (`filterModelsByQuery`), `tests/unit/ui/playground-model-search-4086.test.tsx`. ([#6811](https://github.com/diegosouzapw/OmniRoute/pull/6811)) +- **feat(usage):** Antigravity/agy quota widget now surfaces the **weekly** window alongside the existing per-model 5-hour window ([#4017](https://github.com/diegosouzapw/OmniRoute/issues/4017)) — the weekly limit isn't part of the per-model `retrieveUserQuota` response the fetcher already calls; it only appears in a separate, undocumented `retrieveUserQuotaSummary` RPC that groups models into families ("Gemini Models", "Claude and GPT models") with one weekly bucket per family. A new `usage/antigravityWeeklyQuota.ts` leaf fetches that RPC (cached, best-effort — a failure or unavailable RPC never breaks the existing per-model quotas) and parses the weekly bucket per group into `gemini_weekly`/`claude_gpt_weekly` quota entries, merged into the same `quotas` map the widget already renders generically. Regression guard: `tests/unit/antigravity-weekly-quota-4017.test.ts` (bucket parsing, the alternate `quotaSummary`-nested envelope, and end-to-end merge via `getUsageForProvider`). ([#6818](https://github.com/diegosouzapw/OmniRoute/pull/6818)) +- **feat(codex):** Codex CLI compatibility shim — the Responses API `response.created`/`response.in_progress`/`response.completed` payloads now carry a `model` field (previously absent), and for Codex-CLI-originated requests it echoes the client-requested, effort-suffixed model id (e.g. `gpt-5.5-xhigh`) instead of the bare upstream id (`gpt-5.5`), so the Codex CLI status line/model button shows the active reasoning effort ([#3697](https://github.com/diegosouzapw/OmniRoute/issues/3697)). `openaiToOpenAIResponsesResponse` (`open-sse/translator/response/openai-responses.ts`) now threads the upstream model into the Responses event objects; a new `isCodexOriginatedHeaders()` (`open-sse/config/codexIdentity.ts`, reusing PR #3481's `originator`/User-Agent detection) makes chatCore's existing opt-in `echoRequestedModelName` (#1311) model-echo pipeline fire automatically for Codex clients regardless of the setting, detected by request headers so it still applies when `codex/gpt-5.5-xhigh` is routed through a combo to a non-codex upstream; `echoModelInObject`/`echoModelInSseLine` (`open-sse/services/responseModelEcho.ts`) now also rewrite the nested `response.model` field the Responses API uses. `/v1/models` still returns `models: []` for Codex (unchanged). Regression guard: `tests/unit/codex-effort-model-echo-3697.test.ts`. ([#6820](https://github.com/diegosouzapw/OmniRoute/pull/6820)) +- **Z.ai Web (free web-session provider)**: new `zai-web` web-cookie provider drives the free chat.z.ai consumer chat UI via a pasted browser session cookie, distinct from the existing API-key `zai`/`glm`/`glm-cn`/`glmt` providers (`api.z.ai`) — modeled on the `doubao-web`/`venice-web` cookie executors and the pre-existing `chatglm-web` credential requirement/token-extraction entries. `ZaiWebExecutor` (`open-sse/executors/zai-web.ts`) posts to `chat.z.ai/api/chat/completions` with the cookie forwarded both as `Cookie` and as `Authorization: Bearer `, and normalizes both z.ai's internal `delta_content`/`phase` SSE envelope and a pass-through OpenAI-shaped `choices[].delta` frame into standard chat-completion chunks. Registered in `WEB_COOKIE_PROVIDERS`, `WEB_SESSION_CREDENTIAL_REQUIREMENTS`, the provider registry (`zai-web` entry, GLM-4.6/4.5/4.5V models), and `tokenExtractionConfig.ts` for in-app cookie capture. Regression guard: `tests/unit/executor-zai-web.test.ts` (16 tests — token extraction, frame parsing for both SSE shapes, streaming and non-streaming aggregation, error paths). (#4056) ([#6823](https://github.com/diegosouzapw/OmniRoute/pull/6823)) +- feat(dashboard): import multiple, possibly different providers from a CSV/JSON file — per-row validation, a checklist to pick which parsed rows to import, and a new `POST /api/providers/import` route with partial-failure results (#6836) +- **feat(compression):** update the vendored **GCF** codec behind the **Headroom** engine to spec **v3.2 (nested flattening)** ([#6837](https://github.com/diegosouzapw/OmniRoute/issues/6837)). Homogeneous arrays whose rows carry nested objects/arrays now tabularize via `>`-prefixed path fields instead of a low-yield per-row fallback, so nested MCP tool-result rows (`meta:{...}`, `tags:[...]`) compact like flat rows. On representative shapes the update takes deeply-nested payloads the old codec left near-uncompressed from ~3% to ~32% vs JSON (k8s pods, `cl100k_base`), with shallow-nested rows seeing a small bump and flat arrays unchanged. Re-vendored from current gcf-typescript (zero runtime deps, MIT, SPDX-marked, generic-profile only); also folds in the `[N]:` inline-array quoting fix and canonical decimal formatting. Round-trip stays lossless (order-insensitive), and the decoder is hardened against prototype pollution (a `__proto__`/`constructor` path segment never mutates `Object.prototype`, and keys shadowing built-ins like `toString` now round-trip correctly instead of misparsing). Regression guard: `tests/unit/compression/headroom-smartcrusher.test.ts` (deep-nested + prototype-pollution cases). +- **feat(sse):** OpenRouter quota tracking — a dedicated fetcher polls `/api/v1/key` + `/api/v1/credits` (per-key credit cap/remaining/reset, daily/weekly/monthly USD spend, BYOK usage) with a 45s cache and graceful degradation, a local per-account counter tracks the `:free`-model 50-or-1000-per-day + 20 RPM windows (corrected from `X-RateLimit-*` headers and `Retry-After` on 429), and OpenRouter `402` responses now lock the connection with a real cooldown instead of triggering an immediate reselection of the same credit-exhausted key (#6842). +- **feat(sse):** live gRPC-web quota fetcher for Grok Build (`grok-cli`) — polls xAI's shared weekly credit pool (`grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig`) with the connection's existing bearer token, hand-decoding the framed/raw protobuf response (proto3 omission = 0% used, malformed/expired-token fails open) instead of relying solely on the static 864 req/day estimate, which now serves as an explicit fallback when the live fetch is unavailable (#6844). +- feat(sse): add dual-window quota tracking for the `v0-vercel` provider — polls the credits (`/v1/user/billing`) and daily Platform-API operation (`/v1/rate-limits`) endpoints with the existing routing API key, defensively degrading to an `unknown` billing type rather than misparsing a future v0 billing-model migration, feeding preflight + the dashboard's Provider Quota card (#6845). +- feat(sse): add a static local RPM budget (default 40/min, operator-overridable), per-model 429 scoping (already covered by #6773's `passthroughModels`), and a per-connection concurrency cap (default 6, operator-overridable) for the `nvidia` (NVIDIA NIM) provider, which sends no rate-limit headers and has no usage API — Phase 1 of client-side quota tracking; adaptive AIMD learning and the dashboard quota card are deferred follow-ups (#6846). +- feat(sse): add quota tracking for the `agentrouter` provider — polls the New-API `/api/user/self` balance endpoint with a separate System Access Token + `New-Api-User` id (configured via `providerSpecificData.consoleApiKey` / `newApiUserId`), converting raw quota units into a dollar balance and feeding preflight + the dashboard's Provider Quota card (#6850). +- **feat(providers):** Add GPT-5.6 support across OpenAI API, Codex, and ChatGPT Web, including Codex Max/Ultra efforts, VS Code metadata, Fast-tier credit accounting, curated live discovery, the Codex 0.144.1 client identity, and correct chat routing for models that also support image generation ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- **chore(providers):** Align emitted Claude Code identity headers, bridge fingerprints, provider profiles, and documented defaults with claude-cli 2.1.207 ([#6862](https://github.com/diegosouzapw/OmniRoute/pull/6862)) - thanks @backryun +- feat(api): add a structured `X-Routing-Fallback-Reason` header to relay routing responses, exposing a stable machine-readable reason code alongside the legacy `X-Routing-Fallback` detail string (#6872) +- **feat(api):** new **GET /api/usage/model-latency-stats** management endpoint exposes the existing rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate) already used internally by auto-combo routing — supports `windowHours`/`minSamples`/`maxRows`/`provider`/`model` filters (#6873). +- **feat(providers):** add a `vibeproxy-openai` provider-node preset to `POST /api/provider-nodes` — defaults name/prefix/apiType for VibeProxy's local OpenAI-compatible gateway and normalizes the caller-supplied base URL to its `/v1` root; `baseUrl` remains mandatory. (#6874, idea from #6137 by @KooshaPari) +- feat(usage): add avgTtftMs/avgE2ELatencyMs/avgTokensPerSecond to `getModelLatencyStats()` and feed them into auto-combo's speed-ranking factor (#6875) +- feat(sse): per-model default `reasoning_effort` (`ModelSpec.defaultReasoningEffort`, injected only when the request carries no reasoning field) and make `no-think/` express `reasoning_effort:"none"` instead of deleting the field on the OpenAI path, so thinks-by-default models actually stop thinking (#6879) +- **feat(providers):** let a custom/openai-compatible connection opt into prompt-cache behavior via a per-connection `cache` capability override, unblocking `prompt_cache_key` injection, the compression cache-aware guard, and `cache_control` passthrough for `openai-compatible-chat-`-style connections. (thanks @andrea-kingautomation) +- **feat(dashboard):** add a Type filter (No Signup / OAuth Login / API Key) and an "Easiest first" sort toggle to Free Provider Rankings, so zero-setup NOAUTH providers can be surfaced without eyeballing the Type column. (#6915) +- **feat(providers):** expose an editable base-URL field on the ComfyUI connection so Docker-network setups (e.g. `http://comfyui:8188`) work for image, video, and music generation ([#6928](https://github.com/diegosouzapw/OmniRoute/issues/6928)) +- **feat(providers):** refresh the curated OpenRouter embeddings catalog (`open-sse/config/embeddingRegistry.ts`) with the current lineup — `openai/text-embedding-3-small`/`-large`, `qwen/qwen3-embedding-8b`/`-4b`, `baai/bge-m3`, `mistralai/mistral-embed-2312`, `google/gemini-embedding-001` — and fold curated embedding/rerank entries into OpenRouter's live model-discovery response (`src/app/api/providers/[id]/models/route.ts`), additively and deduped by id, so they no longer only appear on the no-config `local_catalog` fallback. OpenRouter serves embeddings via a dedicated `/api/v1/embeddings` endpoint (omitted from `/v1/models`), so the live-discovery success path previously returned chat models only ([#6976](https://github.com/diegosouzapw/OmniRoute/issues/6976)). Regression guard: `tests/unit/openrouter-embeddings-catalog-6976.test.ts`. +- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977)) +- **feat(oauth):** Add a one-click browser (PKCE) login for Grok Build (`grok-cli`) ALONGSIDE the existing device-code flow — reusing the same `auth.x.ai` authorize/token endpoints and public client id as the sibling `xai-oauth` provider on its own loopback port — while keeping the pre-existing device-code method and the paste-token/`auth.json` import flow both available; the connect modal lets the user pick "Device Code", "Browser Login", or "JWT Token" ([#7013](https://github.com/diegosouzapw/OmniRoute/issues/7013)) +- **feat(sse):** Add optional-enum `null`-omission idiom for Responses-API (codex) strict-mode tool schemas, closing the #6951 follow-up ([#7023](https://github.com/diegosouzapw/OmniRoute/issues/7023)) +- **feat(auth):** accept the `x-goog-api-key` header for client-facing auth so `gemini-cli` and other `@google/genai`-based clients can use OmniRoute as a native `/v1beta` gateway (#7034 — thanks @QRcode1337). +- feat(sse): add a local dual-window (5h + 7d, per-account) quota tracker for the `freemodel-dev` provider, feeding preflight + the dashboard's Provider Quota card with user-overridable request caps (`FREEMODEL_5H_REQUEST_LIMIT` / `FREEMODEL_7D_REQUEST_LIMIT`) since FreeModel publishes no usage API — phase 1 of #7075 (tracker + registration); live hot-path request metering and the forward-compatible endpoint prober are tracked as follow-ups. +- **feat(api):** opt-in scheduled auto-sync for free-proxy sources (`src/lib/freeProxyProviders/scheduler.ts`) — periodically re-runs the free-proxy provider `sync()` calls (iplocate, proxifly, oneproxy, webshare) that previously only ran via a manual `POST /api/settings/free-proxies/sync`, so a seeded pool no longer goes stale as free-proxy lists rotate; gated by `FREE_PROXY_AUTO_SYNC_ENABLED` (default `false`) and `FREE_PROXY_AUTO_SYNC_INTERVAL_MS` (default 30min, floor-clamped to 5min), reuses the existing `isBuildProcess()`/`OMNIROUTE_DISABLE_BACKGROUND_SERVICES` guards, and shares one `runFreeProxySyncCycle()` code path with the manual route; `GET /api/settings/free-proxies/stats` now also reports `autoSync: { enabled, intervalMs }` (#7079 — thanks @chirag127). +- **feat(kiro):** register the GPT-5.6 Sol/Terra/Luna model family (272k context window). (thanks @SemonCat) +- **feat(dashboard):** show the Codex subscription plan label in provider connection rows and the quota view, falling back to the plan captured at OAuth import when the live usage endpoint doesn't report one. (thanks @CarmeloCampos) +- **feat(dashboard):** add a "Reorder" button to provider connections that sorts them by availability (using OmniRoute's connection-cooldown/testStatus model), persisting the new priority order. (thanks @fzrilsh) +- **feat(dashboard):** add 180D and 365D periods to the Cost Explorer range selector. The new ranges thread through `parseCostRange`/`COST_RANGE_VALUES` and the `getRangeStartIso` handlers in the analytics and requests-by-provider-date usage routes, so cost/usage analytics can be viewed over a half-year and full-year window (#7213) +- **feat(sse):** GitHub Copilot Claude models now route through Copilot's native `/v1/messages` endpoint (prompt-cache token counts, no more lossy tool-call round-trip). (thanks @yidecode) +- **feat(mitm):** Antigravity MITM model mappings now support an optional per-model reasoning-effort override (Default/None/Low/Medium/High/XHigh) alongside the destination-model remap. (thanks @trfi) +- **feat(sse):** add native xAI Grok Imagine video generation provider — `xai/grok-imagine-video` on `/v1/videos/generations` using your own xAI key, instead of only via the kie proxy market. (thanks @anndev-69) +- **feat(cli):** add Grok Build CLI tool setup — writes a `[model.omniroute]` custom model into `~/.grok/config.toml` and restores your previous default on Reset. (thanks @rixzkiye) +- **feat(provider):** add Chenzk API OpenAI-compatible gateway. (thanks @CahyokPutraDev99) +- **feat(dashboard):** add a per-operator "hide this quota row" toggle to the usage dashboard's provider limit cards, persisted per-provider in settings. (thanks @nguyenha935) +- **feat(sse):** session affinity (`X-Session-Id` / `x-codex-session-id` / `x-omniroute-session`) now works for **any** provider, not just Codex — the `codex`-only early-return in `resolveSessionAffinityTtlMs()` was removed, and the global TTL setting was renamed `codexSessionAffinityTtlMs` → `sessionAffinityTtlMs` (dashboard label updated to "Session affinity") with a backward-compatible migration that carries over an existing Codex TTL as the new default (#7274 — thanks @tenshiak). +- **feat(sse):** `gemini-web` now honors the OpenAI `tools` array by wiring the existing `webTools.ts` prompt-emulation shim (already used by 11 other web-cookie executors) — the tool contract is serialized into the prompt typed into the Gemini web UI, and `{...}` blocks in the response are parsed back into `tool_calls` (malformed JSON degrades to ordinary chat content, never an error), including for streaming requests; `docs/reference/PROVIDER_REFERENCE.md` gained a "Tool calling" column (`native`/`emulated`/`none`) for providers with confirmed ground truth. `claude-web` still silently drops `tools` pending a separate emulate-vs-native design decision (#7286). +- **feat(eval):** added a router-eval harness (`npm run eval:router`, `eval:router:compare`, `eval:router:patch-compare`, `eval:router:search`, `eval:router:trends`, `check:router-eval`) that replays routing decisions — from NDJSON corpora or the `usage_history`/`call_logs` SQLite tables — into an AIQ (success/latency/cost) score, compares baseline vs. candidate router configs with a retained-run regression gate, and ranks Pareto-optimal candidates; a sibling tool to the existing `eval:compression` harness (#7318 — thanks @KooshaPari). +- **feat(services):** introduce a `ServiceProviderPlugin` contract (`src/lib/services/providerPlugins/`) that packages what was previously spread across `bootstrap.ts`'s inline `SERVICES[]` config and `serviceBackends.ts`'s manifest template into one shape per embedded-service backend; migrates `9router` through it end to end as the first proof, with `cliproxy`/`mux`/`bifrost` left completely unchanged on their pre-existing code paths — `cliproxyapi` migration, executor-routing consolidation, and manifest-path wiring are follow-up work (#7333). +- feat(routing): wire `interceptFetch` into the chat pipeline — `resolveInterceptFetch(provider, model)` (a structural twin of `resolveInterceptSearch`) and the new `open-sse/services/webFetchInterception.ts` module rewrite a provider-native `web_fetch` tool declaration into a synthetic `omniroute_web_fetch` function tool, dispatched through the existing tool-call execution path to OmniRoute's own `/v1/web/fetch` instead of the upstream provider running it natively; strictly opt-in per provider/model (undefined/off leaves the request byte-identical to today), with a new dashboard toggle on the provider detail page covering both `interceptSearch` and `interceptFetch` (#7339, Phases 3-4 of #3384) +- feat(dashboard): confirm before removing a single connection, naming the account, mirroring the existing batch-delete confirm UX (#7361) +- **feat(providers):** Add a first-class xAI OAuth PKCE provider for `api.x.ai` models, including Grok 4.5 and refresh-token rotation ([#7399](https://github.com/diegosouzapw/OmniRoute/pull/7399)) — thanks @fenix007 +- **feat(dashboard):** surface in-product guidance for the Settings → Prompt Compression engines — each `engineCatalog.ts` entry now carries a `guidance` block (quality/latency tradeoffs, lossy flag, cache impact) sourced from `docs/compression/*.md`, rendered as an expandable per-engine detail with a "safe default" indicator for lossless engines (Session Dedup, CCR, Lite, Headroom) plus a link to the full compression guide (#7530). +- **feat(providers):** Complete GHE Copilot OAuth provider implementation with device-code flow, validation, error sanitization, and DNS provisioning mapping ([#7546](https://github.com/diegosouzapw/OmniRoute/pull/7546)) +- feat(providers): grok-web's add-connection dialog now shows a proactive hint explaining that grok.com's `cf_clearance` cookie is pinned to the IP, User-Agent, and TLS fingerprint of the browser that earned it — on a 403, paste the exact browser User-Agent into the existing Custom User-Agent field under Advanced Settings and reuse the same IP/proxy (#7567) +- **feat(providers):** register `lmstudio` in the embedding provider registry (`open-sse/config/embeddingRegistry.ts`) — LM Studio's local OpenAI-compatible `/v1/embeddings` endpoint, no auth required, passthrough model list (a user-configured provider_node still takes priority). Previously any `lmstudio/` embedding request failed with `"Unknown embedding provider: lmstudio"` even though the model appeared fine in `/v1/models` ([#7601](https://github.com/diegosouzapw/OmniRoute/issues/7601) — thanks @ekinnee). Regression guard: `tests/unit/lmstudio-embedding-provider-7601.test.ts`. +- feat(sse): honor a no-auth provider connection's **Excluded Models** field (`providerSpecificData.excludedModels`) in the auto-combo/fusion candidate pool builder, so an excluded no-auth model (e.g. `minimax-m3-free`) is filtered out upfront instead of only failing over after being picked (#7622). +- **feat(dashboard):** proxy-assignment UX quality-of-life fixes — the per-connection proxy badge now shows the saved proxy's **name** instead of always falling back to its hostname (so distinct proxies sharing a domain no longer render identically), the "Proxy Config" modal's saved-proxy dropdown is now alphabetized by name, and the modal defaults to the **Saved** tab (instead of Custom) whenever the target scope has no assignment yet and at least one saved proxy already exists (#7643 — thanks @tenshiak). +- feat(providers): `zai-web` (chat.z.ai) now wires live `/models` discovery through the shared PROVIDER_MODELS_CONFIG pipeline (cache → hardcoded local-catalog fallback), instead of only serving a static 3-model catalog whose ids had started 404ing upstream (#7678 — thanks @andrea-kingautomation). The `chat.z.ai/api/models` response shape and Bearer-only auth are unverified pending a live cookie check before merge. +- **feat(perplexity):** Refresh Perplexity Web model mappings and Search API filters while keeping `/v1/models` scoped to API-key validation instead of curated catalog discovery ([#7687](https://github.com/diegosouzapw/OmniRoute/pull/7687)) — thanks @backryun +- Generic OpenAI-compatible model sync now captures a provider's upstream `reasoning.supported_efforts` (in addition to the pre-existing flat `supportedThinkingEfforts` shape), surfaces it in the model catalog as `capabilities.effort_tiers`, and advertises `/-{effort}` request-time alias ids for catalog-only clients — mirroring the existing per-model reasoning-effort plumbing (#6879). Codex and Kimi are excluded since they already own their own effort-suffix mechanism. +- **feat(dashboard):** Kimi (Moonshot AI) official-partnership highlight on the providers dashboard — Kimi-family providers (`kimi-coding`, `kimi-web`, `moonshot`) now render first within their category/group, and their card gets a Kimi-blue (`#1783FF`) accent border/glow plus an "Official Supporter" badge; presentation-only, routing/fallback order is unaffected (#7775). +- feat(providers): let any provider connection — built-in or custom — be pinned to an explicit routing tier (free/cheap/premium) via a new `/api/settings/tier-config` route and an Advanced Settings tier selector; `TierCoverageWidget` now honors the override too (#7818) +- feat(routing): add a read-only `GET /v1/auto-combo/{channel}/candidates` endpoint listing an `auto/*` channel's candidate pool with live reachability (provider circuit breaker, connection cooldown, model lockout), plus a per-API-key candidate exclusion list enforced in the `auto/*` candidate-pool builder — users with no overrides configured see byte-identical routing to today (#7819). +- feat(providers): copilot-m365-web tone-selected model variants (#7872) +- **feat(shared):** Add canonical numeric coercion helpers (`toNumber`, `toNumberOrNull`, `toNumberArray`) in `src/shared/utils/numeric.ts` with table-driven tests and a lint rule barring new local `toNumber` definitions, then migrate the report/analytics tier (usage analytics route, provider metrics route, usage stats, usage history helpers, call-log formatting, cost-analysis A2A skill) off their local duplicates ([#7879](https://github.com/diegosouzapw/OmniRoute/issues/7879)) +- feat(mcp): add a narrow `mcp:connect` API-key scope for the `/api/mcp/` LOCAL_ONLY carve-out (separate from `manage`/`admin`) and populate `authInfo.scopes` from the caller's real per-key scopes over HTTP/SSE so `scopeEnforcement.ts` prefers per-key scopes over the `OMNIROUTE_MCP_SCOPES` env fallback when enforcement is enabled (#7895). +- feat(dashboard): provider tab account search (id/tag/name/email substring, cross-page) + mirrored top pagination bar + pagination for the tagged/grouped connections view (#7937) +- feat(sse): classify grok-web Cloudflare anti-bot blocks + gated browser-backed cf_clearance path (#8019) +- Teach the model the CCR retrieve protocol (marker → `omniroute_ccr_retrieve`, verbatim 24-char hash, `dedup:ref` look-back) on the first marker, gated on MCP-tool capability (#8033) +- Add a per-model/endpoint compression exclusion filter: name model ids or `provider/model` patterns (`*` wildcard) that must never be compressed, checked before any engine runs so the request passes through byte-identical; configurable from a new Dashboard → Compression → Exclusions tab (#8034) +- **feat(i18n):** zh-CN terminology glossary + consistency gate + 提供商→提供者 normalization — one-shot pass across `src/i18n/messages/zh-CN.json` (679 substitutions) and `bin/cli/locales/zh-CN.json` (54) mirroring #8024's zh-TW pass, a new versioned glossary (`scripts/i18n/glossary/zh-CN.json`) and protected-terms list (`scripts/i18n/glossary/protected-terms.json`), a pure-function consistency check (`scripts/i18n/check-glossary-consistency.mjs`, `npm run i18n:check-glossary`) wired into CI as `i18n-glossary-zhcn`, and zh-CN added to the visual-QA harness default locales (#8038). +- **feat(dashboard):** The Codex quota card no longer shows latent, never-used per-feature rate-limit ceilings (e.g. `GPT-5.3-Codex-Spark`) as permanent 100% rows with a meaningless always-full reset — they now appear only once the feature is actually used. Per-feature window labels track the payload's `limit_name`, and each window is labeled by its real `limit_window_seconds` (so a 7-day `primary_window` shows "Weekly" instead of "Session"). ([#8051](https://github.com/diegosouzapw/OmniRoute/issues/8051)) +- feat(providers): native Fish Audio TTS provider on /v1/audio/speech (#8099) +- **feat(codex):** add bounded multi-reference PNG/JPEG/WebP image editing (up to 8 references and 20 MiB decoded in aggregate) through the OpenAI-compatible `/v1/images/edits` route by reusing Codex Responses hosted-image tooling, OAuth, proxies, sanitized logs/errors, and OpenAI Images response formatting ([#8122](https://github.com/diegosouzapw/OmniRoute/pull/8122)) — thanks @xiaoyaner0201 +- refactor(sse): classify SSE critical-path empty catches + add CONTRIBUTING convention (#8142) +- feat(db): persist caller session tag into call_logs for per-session cost attribution (#8249) +- feat(api): quota-aware fallback routing for web-fetch providers (#8297) +- feat(providers): map upstream reasoning-level metadata in openai-compatible discovery (#8347) +- **feat(providers):** weekly quota for xAI OAuth (Grok) (`xai-oauth` / `xao`) via shared cli-chat-proxy billing (`creditUsagePercent`), with fail-open self-tracked fallback ([#8471](https://github.com/diegosouzapw/OmniRoute/pull/8471)) — thanks @allanvb +- feat(jobs): `backup auto enable` schedule is now executed server-side — the cron expression, cloud/encrypt/retention settings written by the CLI are consumed by a new `startBackupScheduleJob()` tick registered alongside `startBudgetResetJob()` in `instrumentation-node.ts`; includes a zero-dependency 5-field cron matcher ([#8513](https://github.com/diegosouzapw/OmniRoute/issues/8513)) +- **feat(ci):** automate ratchet shrink-banking so file-size/complexity caps stop outliving their files after successful shrinks (#8584) ([#8612](https://github.com/diegosouzapw/OmniRoute/pull/8612)) — thanks @MumuTW +- **feat(providers):** live monthly credit quota for Firecrawl (`GET /v2/team/credit-usage`) in Provider Limits / preflight ([#8759](https://github.com/diegosouzapw/OmniRoute/pull/8759)) — thanks @allanvb +- **feat(search):** add Firecrawl to `POST /v1/search` supported providers with two sources (web|news) ([#8814](https://github.com/diegosouzapw/OmniRoute/pull/8814)) — thanks @allanvb +- **feat(adobe-firefly):** reference-image attach for generate + OpenAI `/v1/images/edits` support (follow-up to #8006). Uploads sources to Firefly storage (`POST /v2/storage/image`), then submits `referenceBlobs` on 3P generate-async (nano multi-ref `usage:general`; gpt-image `usage:subject`). Wire matches live `firefly.adobe.com` captures. Also routes built-in edits to the same path (up to 4 refs). +- **Homologation suite**: new `npm run homolog` runs the full release-homologation battery against the deployed VPS — health/version parity, API + real SSE streaming with an ephemeral API key (created and revoked by the run), minimal-cost real-provider smoke (promptfoo generated from the live catalog), and a Playwright sweep that loads every dashboard route and exercises the API-key UI flow — emitting a unified CTRF report that backs the release STOP #2 checklist +- **feat(mcp):** add a read-only Local Corpus context source with bounded incremental text indexing, path-containment controls, an authenticated settings API, and three scoped MCP tools. +- feat(providers): notion-web live model discovery via getAvailableModels (spaceId + token_v2 cookie) +- Provider connections can now be shown or hidden individually on the Provider Quota page. The + visibility setting is available on each account in the provider detail view and does not affect + routing or account activation. +- docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). +### ⚡ Performance + +- **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 +- **perf(db):** add jitter to stagger due-on-restart connections ([#6919](https://github.com/diegosouzapw/OmniRoute/pull/6919)) — thanks @oyi77 +- **perf(startup):** warm model catalog cache at module init ([#6920](https://github.com/diegosouzapw/OmniRoute/pull/6920)) — thanks @oyi77 +- **perf(db):** add temp_store=MEMORY pragma to SQLite init ([#6921](https://github.com/diegosouzapw/OmniRoute/pull/6921)) — thanks @oyi77 +- **perf(db):** cap modelLockouts eviction at 1000 entries ([#6923](https://github.com/diegosouzapw/OmniRoute/pull/6923)) — thanks @oyi77 +- **perf:** wrap ComboCard, HeroSection in React.memo ([#7070](https://github.com/diegosouzapw/OmniRoute/pull/7070)) — thanks @oyi77 + +- **perf:** Date.now hoist, hasActiveDeltaValue hoist, buffer.split guard in SSE stream ([#7066](https://github.com/diegosouzapw/OmniRoute/pull/7066)) — thanks @oyi77 +- **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 +- **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma +- **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +### 🐛 Bug Fixes + +- **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 +- **fix(grok):** strip reasoningEffort for grok cli models ([#6938](https://github.com/diegosouzapw/OmniRoute/pull/6938)) — thanks @CitrusIce +- **fix(6954,6953):** preserve system role + strip empty-signature thinking blocks ([#6982](https://github.com/diegosouzapw/OmniRoute/pull/6982)) — thanks @rafaumeu +- **fix(6980):** classify Cloudflare AI neuron exhaustion as quota_exhausted ([#6983](https://github.com/diegosouzapw/OmniRoute/pull/6983)) — thanks @rafaumeu +- **fix(dashboard):** hide disabled provider connections from combo builder ([#6984](https://github.com/diegosouzapw/OmniRoute/pull/6984)) +- **fix(providers):** cap grok-cli tools at 200 for cli-chat-proxy ([#6986](https://github.com/diegosouzapw/OmniRoute/pull/6986)) +- **fix(6848):** auto-cleanup for telemetry tables causing OOM ([#6988](https://github.com/diegosouzapw/OmniRoute/pull/6988)) — thanks @rafaumeu +- **fix(models):** preserve direct-model combo metadata ([#6993](https://github.com/diegosouzapw/OmniRoute/pull/6993)) — thanks @JxnLexn +- **fix:** DDG circuit breaker (#6999) + null content validation (#7000) ([#7001](https://github.com/diegosouzapw/OmniRoute/pull/7001)) — thanks @rafaumeu +- **fix(models):** preserve chat-capable image model rows ([#7004](https://github.com/diegosouzapw/OmniRoute/pull/7004)) — thanks @xz-dev +- **fix(codex):** preserve GPT-5.6 reasoning contract ([#7012](https://github.com/diegosouzapw/OmniRoute/pull/7012)) — thanks @xz-dev +- **fix(base-red):** align least-used combo tests with executionKey usage keying ([#7015](https://github.com/diegosouzapw/OmniRoute/pull/7015)) +- **fix:** infer bare models from active synced catalogs ([#7028](https://github.com/diegosouzapw/OmniRoute/pull/7028)) — thanks @guanbear +- **fix(auggie):** update model registry to match v0.32.0 CLI model IDs ([#7032](https://github.com/diegosouzapw/OmniRoute/pull/7032)) — thanks @oyi77 +- **fix(sse):** register ollama-cloud in USAGE_FETCHER_PROVIDERS (#7026) ([#7041](https://github.com/diegosouzapw/OmniRoute/pull/7041)) — thanks @alltomatos +- **fix(quality):** read cognitiveComplexity= machine line in validate-release-green (#7009) ([#7042](https://github.com/diegosouzapw/OmniRoute/pull/7042)) — thanks @alltomatos +- **fix(providers):** sanitize Claude native output_config.effort (#7044) ([#7050](https://github.com/diegosouzapw/OmniRoute/pull/7050)) — thanks @xier2012 +- **fix(combo):** treat maxInputTokens as an input-only cap in the context filter (#7039) ([#7052](https://github.com/diegosouzapw/OmniRoute/pull/7052)) — thanks @xier2012 +- **fix(antigravity):** collect native part.functionCall into tool calls (#7037) ([#7053](https://github.com/diegosouzapw/OmniRoute/pull/7053)) — thanks @xier2012 +- **fix(responses):** map mid-conversation system turns to developer role (#6954) ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)) — thanks @xier2012 +- **fix(combo):** least-used sorts by per-account executionKey (#7015) ([#7059](https://github.com/diegosouzapw/OmniRoute/pull/7059)) — thanks @xier2012 +- **fix(providers):** AgentRouter model import applies Claude Code wire image to /v1/models (#7016) ([#7060](https://github.com/diegosouzapw/OmniRoute/pull/7060)) — thanks @xier2012 +- **fix(translator):** preserve thinking.budget_tokens: 0 in Claude->Gemini (#6813) ([#7061](https://github.com/diegosouzapw/OmniRoute/pull/7061)) — thanks @xier2012 +- **fix(cloudflare-relay):** avoid invalid regex syntax in generated worker ([#7063](https://github.com/diegosouzapw/OmniRoute/pull/7063)) — thanks @SeaXen +- **fix(dashboard):** strip browser-extension attrs before hydration ([#7073](https://github.com/diegosouzapw/OmniRoute/pull/7073)) — thanks @MrFadiAi +- **fix(relay):** bound Bifrost stream lifetime ([#7093](https://github.com/diegosouzapw/OmniRoute/pull/7093)) — thanks @KooshaPari +- **fix(sse):** recognize xiaomi-tokenplan mimo as a thinking-mode model ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) +- **fix(codex):** strip regex lookaround from tool schema patterns ([#7100](https://github.com/diegosouzapw/OmniRoute/pull/7100)) +- **fix(openai):** strip reasoning_effort when GPT-5.x models carry function tools ([#7101](https://github.com/diegosouzapw/OmniRoute/pull/7101)) +- **fix(compression):** Headroom SmartCrusher skips developer-role messages (port from 9router#2132) ([#7102](https://github.com/diegosouzapw/OmniRoute/pull/7102)) +- **fix(providers):** surface a warning on 404 model_not_found in OpenAI-compatible Check (port from 9router#2032) ([#7103](https://github.com/diegosouzapw/OmniRoute/pull/7103)) +- **fix(executors):** forward X-Session-ID/X-Title agent metadata headers ([#7104](https://github.com/diegosouzapw/OmniRoute/pull/7104)) +- **fix(cli):** verify better-sqlite3 native binary is actually loadable ([#7105](https://github.com/diegosouzapw/OmniRoute/pull/7105)) +- **fix(sse):** sanitize non-ok Antigravity streaming error body (port from 9router#2461) ([#7106](https://github.com/diegosouzapw/OmniRoute/pull/7106)) +- **fix(providers):** add MiniMax image-generation provider ([#7108](https://github.com/diegosouzapw/OmniRoute/pull/7108)) +- **fix(sse):** handle space-separated arg name/value in Composer tool calls (port from 9router#1811) ([#7116](https://github.com/diegosouzapw/OmniRoute/pull/7116)) +- **fix(cli):** remove MITM DNS spoof entries before killing server process ([#7117](https://github.com/diegosouzapw/OmniRoute/pull/7117)) +- **fix(dashboard):** include never-tested connections in combo builder active-provider list (port from 9router#2057) ([#7118](https://github.com/diegosouzapw/OmniRoute/pull/7118)) +- **fix(api):** check Vercel SSO-protection PATCH response on relay deploy ([#7119](https://github.com/diegosouzapw/OmniRoute/pull/7119)) +- **fix(combos):** reject oversized fusion panels before fan-out (port from 9router#1905) ([#7120](https://github.com/diegosouzapw/OmniRoute/pull/7120)) +- **fix(combo):** detect empty content_block in streaming SSE peek ([#7121](https://github.com/diegosouzapw/OmniRoute/pull/7121)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by clientId match (port from 9router#1253) ([#7122](https://github.com/diegosouzapw/OmniRoute/pull/7122)) +- **fix(tests):** vitest UI suite back to green (69 fails triaged — WS6.1) ([#7127](https://github.com/diegosouzapw/OmniRoute/pull/7127)) +- **fix(auto):** use p95 fallback in speed factors ([#7128](https://github.com/diegosouzapw/OmniRoute/pull/7128)) — thanks @KooshaPari +- **fix(models):** update Anthropic model contextLength to 1M ([#7129](https://github.com/diegosouzapw/OmniRoute/pull/7129)) — thanks @HouMinXi +- **fix(ci):** raise dast-smoke timeout 12->25min (build alone eats up to 11min) ([#7139](https://github.com/diegosouzapw/OmniRoute/pull/7139)) +- **fix(compression):** lazy-load typescript in RTK codeStripper so prod-lean deploys don't break (#7096) ([#7164](https://github.com/diegosouzapw/OmniRoute/pull/7164)) — thanks @alltomatos +- **fix(providers):** accept m365.cloud.microsoft for copilot-m365-web token (#7078) ([#7166](https://github.com/diegosouzapw/OmniRoute/pull/7166)) — thanks @xier2012 +- **fix(executors):** disable parallel tools for Codex Responses Lite ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(tests+providers):** env-dependent tests exposed by GH-hosted runners (#6634 selfref shallow checkout + yuanbao live-network 401) ([#7174](https://github.com/diegosouzapw/OmniRoute/pull/7174)) +- **fix(combo):** reject known context overflow without exhausting providers ([#7177](https://github.com/diegosouzapw/OmniRoute/pull/7177)) — thanks @JxnLexn +- **fix:** add static.cloudflareinsights.com to CSP script-src ([#7178](https://github.com/diegosouzapw/OmniRoute/pull/7178)) — thanks @oyi77 +- **fix:** extend turbopack ignoreIssue suppression to compression module (#7051) ([#7180](https://github.com/diegosouzapw/OmniRoute/pull/7180)) +- **fix:** recognize Ollama Cloud session usage-limit 429 as quota-exhausted (#7071) ([#7181](https://github.com/diegosouzapw/OmniRoute/pull/7181)) +- **fix:** preserve relayAuth for pool-referenced relay proxies (#5716) ([#7182](https://github.com/diegosouzapw/OmniRoute/pull/7182)) +- **fix:** wire adaptive context-budget dial into settings schema and DB (#7005) ([#7183](https://github.com/diegosouzapw/OmniRoute/pull/7183)) +- **fix(providers):** DuckDuckGo VQD 429 misclassified as 503 (#6996) ([#7185](https://github.com/diegosouzapw/OmniRoute/pull/7185)) +- **fix(db):** cap OOM probe-failure cycle in getDbInstance() (#6835) ([#7186](https://github.com/diegosouzapw/OmniRoute/pull/7186)) +- **fix:** stop opencode-go quota lookup defaulting to Z.AI endpoint (#7022) ([#7187](https://github.com/diegosouzapw/OmniRoute/pull/7187)) +- **fix(providers):** refresh OpenCode (oc) free-tier model catalog (#6998) ([#7188](https://github.com/diegosouzapw/OmniRoute/pull/7188)) +- **fix:** include proxyId when testing a saved registry proxy (#7080) ([#7189](https://github.com/diegosouzapw/OmniRoute/pull/7189)) +- **fix:** sanitize non-Latin1 chars in combo diagnostic headers (#6612) ([#7190](https://github.com/diegosouzapw/OmniRoute/pull/7190)) +- **fix:** raise main server keepAliveTimeout/headersTimeout above Node's 5s default (#7003) ([#7191](https://github.com/diegosouzapw/OmniRoute/pull/7191)) +- **fix:** route zai-web (and other registry-entry web-cookie providers) connection-test cookie probe through the configured proxy (#7058) ([#7192](https://github.com/diegosouzapw/OmniRoute/pull/7192)) +- **fix(providers):** reject chat requests for cloud-agent-only jules provider (#6699) ([#7193](https://github.com/diegosouzapw/OmniRoute/pull/7193)) +- **fix:** restore mobile grid-cols-1 fallback on quota page card grid (#7072) ([#7194](https://github.com/diegosouzapw/OmniRoute/pull/7194)) +- **fix:** wire modelAliases fetch into HermesAgentToolCard (#7151) ([#7195](https://github.com/diegosouzapw/OmniRoute/pull/7195)) +- **fix:** surface real claude-web error body for non-SSE 400s (#7134) ([#7196](https://github.com/diegosouzapw/OmniRoute/pull/7196)) +- **fix(dashboard):** agent bridge dns toggle uses POST, not PUT (#7157) ([#7197](https://github.com/diegosouzapw/OmniRoute/pull/7197)) +- **fix:** stop duplicating text in Gemini Web streamed responses (#7163) ([#7198](https://github.com/diegosouzapw/OmniRoute/pull/7198)) +- **fix:** filter hidden custom models out of legacy combo model picker (#7156) ([#7199](https://github.com/diegosouzapw/OmniRoute/pull/7199)) +- **fix(dashboard):** implement missing handleToggleSource on Free Pool tab (#7161) ([#7200](https://github.com/diegosouzapw/OmniRoute/pull/7200)) +- **fix:** honor combo-level proxy assignments from the registry (#7149) ([#7201](https://github.com/diegosouzapw/OmniRoute/pull/7201)) +- **fix(ci):** run quality gates on Mergify merge-queue draft PRs (anchor check never ran, queue always dequeued) ([#7202](https://github.com/diegosouzapw/OmniRoute/pull/7202)) +- **fix:** add dashboard-scoped typecheck gate covering src/app/(dashboard) TSX (#7033) ([#7203](https://github.com/diegosouzapw/OmniRoute/pull/7203)) +- **fix(guardrails/chat):** stop Vision Bridge hijacking credentialed models to opencode-zen ([#7204](https://github.com/diegosouzapw/OmniRoute/pull/7204)) — thanks @artickc +- **fix(translator):** preserve Gemini thought parts as reasoning_content on the OpenAI bridge ([#7206](https://github.com/diegosouzapw/OmniRoute/pull/7206)) +- **fix(translator):** register openai response projection for gemini clients ([#7207](https://github.com/diegosouzapw/OmniRoute/pull/7207)) +- **fix(cli):** fast-path --version to skip full CLI bootstrap ([#7208](https://github.com/diegosouzapw/OmniRoute/pull/7208)) +- **fix:** honor PROVIDER_LIMITS_SYNC_SPACING_MS for local/API-key connections (#6916) ([#7214](https://github.com/diegosouzapw/OmniRoute/pull/7214)) +- **fix(api):** bulk-add API keys no longer overwrite existing connections ([#7234](https://github.com/diegosouzapw/OmniRoute/pull/7234)) +- **fix(sse):** route the public OpenAI GPT-5.6 family through the Responses API ([#7242](https://github.com/diegosouzapw/OmniRoute/pull/7242)) +- **fix(providers):** honor configured proxy on Grok Build egress ([#7244](https://github.com/diegosouzapw/OmniRoute/pull/7244)) +- **fix(nvidia):** expand NIM chat model catalog ([#7247](https://github.com/diegosouzapw/OmniRoute/pull/7247)) +- **fix(sse):** reconstruct Claude-format content in synthetic bypass responses ([#7248](https://github.com/diegosouzapw/OmniRoute/pull/7248)) +- **fix(build):** isolate Windows HOME/AppData during next build ([#7249](https://github.com/diegosouzapw/OmniRoute/pull/7249)) +- **fix(cli):** omniroute dashboard respects PORT env when --port is omitted (#7049) ([#7252](https://github.com/diegosouzapw/OmniRoute/pull/7252)) +- **fix(sse):** project non-streaming JSON back to the Gemini/Antigravity envelope ([#7255](https://github.com/diegosouzapw/OmniRoute/pull/7255)) +- **fix(combo):** fall back on Responses SSE failures ([#7256](https://github.com/diegosouzapw/OmniRoute/pull/7256)) — thanks @rushsinging +- **fix(routing):** resolve nested combo-ref panel members in fusion strategy (#6764) ([#7259](https://github.com/diegosouzapw/OmniRoute/pull/7259)) +- **fix(usage):** reset logs and show provider names in analytics ([#7264](https://github.com/diegosouzapw/OmniRoute/pull/7264)) — thanks @SeaXen +- **fix(sse):** silence noisy proxy-failure log on caller-initiated abort ([#7266](https://github.com/diegosouzapw/OmniRoute/pull/7266)) +- **fix(codex):** normalize nested Responses output content ([#7269](https://github.com/diegosouzapw/OmniRoute/pull/7269)) — thanks @JxnLexn +- **fix(combo):** derive session stickiness key from Responses API .input, not just .messages (#7270) ([#7277](https://github.com/diegosouzapw/OmniRoute/pull/7277)) — thanks @alltomatos +- **fix(antigravity):** wrap Pro fallback chain in try/catch for timeout resilience ([#7290](https://github.com/diegosouzapw/OmniRoute/pull/7290)) — thanks @HouMinXi +- **fix(logs):** show saved provider names in request/provider log views ([#7294](https://github.com/diegosouzapw/OmniRoute/pull/7294)) — thanks @SeaXen +- **fix(stream):** reconcile encrypted Codex reasoning visibility without mutating upstream item ([#7304](https://github.com/diegosouzapw/OmniRoute/pull/7304)) +- **fix(build):** packed tarball boot crash — server-ws timeout import escaped the package (#7065 class) ([#7308](https://github.com/diegosouzapw/OmniRoute/pull/7308)) +- **fix(skills):** register cli-skill-collector in the agent-skills catalog (Integration 2/2 base-red) ([#7310](https://github.com/diegosouzapw/OmniRoute/pull/7310)) +- **fix(db):** tolerate unavailable virtual table modules in stats ([#7313](https://github.com/diegosouzapw/OmniRoute/pull/7313)) — thanks @megamen32 +- **fix(router-eval):** retained-optimization gate cleanup ([#7318](https://github.com/diegosouzapw/OmniRoute/pull/7318)) — thanks @KooshaPari +- **fix(ci):** Coverage job timeout 10->20min (lcov reporter pushed it past the old cap) ([#7342](https://github.com/diegosouzapw/OmniRoute/pull/7342)) +- **fix(electron):** normalize hashed standalone externals ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- **fix(db):** stop a 'latest' path segment from disabling backups and migrations ([#7359](https://github.com/diegosouzapw/OmniRoute/pull/7359)) — thanks @danscMax +- **fix(branding):** regenerate raster favicons — white mark was shipped without its gradient tile ([#7390](https://github.com/diegosouzapw/OmniRoute/pull/7390)) — thanks @vzts +- **fix(test):** skip real DNS writes in MITM dynamic-import test ([#7398](https://github.com/diegosouzapw/OmniRoute/pull/7398)) — thanks @HouMinXi +- **fix(antigravity):** streaming passthrough for non-streaming clients ([#7408](https://github.com/diegosouzapw/OmniRoute/pull/7408)) — thanks @HouMinXi +- **fix(build):** align engines.node with SUPPORTED_NODE_RANGE (#7446) ([#7490](https://github.com/diegosouzapw/OmniRoute/pull/7490)) — thanks @alltomatos +- **fix(api):** await params in Agent Bridge DNS route (Next.js 16) (#7271) ([#7492](https://github.com/diegosouzapw/OmniRoute/pull/7492)) — thanks @alltomatos +- **fix(dashboard):** show Obsidian context source card ([#7500](https://github.com/diegosouzapw/OmniRoute/pull/7500)) — thanks @DKotsyuba +- **fix(ci):** fetch full base history in pr-test-policy (shallow graft broke merge-base) ([#7501](https://github.com/diegosouzapw/OmniRoute/pull/7501)) +- **fix(sse):** preserve chat quota across mixed windows ([#7504](https://github.com/diegosouzapw/OmniRoute/pull/7504)) — thanks @webmasterarbez +- **fix(oauth):** surface sanitized device-code error instead of a generic 500 ([#7511](https://github.com/diegosouzapw/OmniRoute/pull/7511)) — thanks @danscMax +- **fix(oauth):** repair qwen + codebuddy-cn device-code endpoints ([#7517](https://github.com/diegosouzapw/OmniRoute/pull/7517)) — thanks @danscMax +- **fix(mitm):** strip trailing assistant prefill to prevent upstream Anthropic 400 errors ([#7520](https://github.com/diegosouzapw/OmniRoute/pull/7520)) — thanks @chirag127 +- **fix(codex):** Test probe uses a ChatGPT-account-supported model (#7521) ([#7524](https://github.com/diegosouzapw/OmniRoute/pull/7524)) +- **fix(codex):** validate refresh_token on import before persisting (#7522) ([#7525](https://github.com/diegosouzapw/OmniRoute/pull/7525)) +- **fix(codex):** non-stream chat 502 'Response body is already used' (single-reader peek) ([#7526](https://github.com/diegosouzapw/OmniRoute/pull/7526)) +- **fix(oauth):** surface tunnel hint when Codex OAuth runs on a remote host (#7523) ([#7527](https://github.com/diegosouzapw/OmniRoute/pull/7527)) +- **fix(sse):** preserve custom tool output images ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) — thanks @loulanyue +- **fix(combo):** failover when upstream SSE is truncated mid-lifecycle ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** prefer public endpoint URLs ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- **fix(cli):** refresh runtime detection accurately ([#7552](https://github.com/diegosouzapw/OmniRoute/pull/7552)) — thanks @nguyenha935 +- **fix(ui):** improve React Flow dark theme ([#7553](https://github.com/diegosouzapw/OmniRoute/pull/7553)) — thanks @nguyenha935 +- **fix(i18n):** treat **MISSING** sync placeholders as absent in EN fallback (#7258) ([#7556](https://github.com/diegosouzapw/OmniRoute/pull/7556)) +- **fix(cli):** Windows cert check/uninstall key off the real CA identity, not a hardcoded legacy host (#7275) ([#7557](https://github.com/diegosouzapw/OmniRoute/pull/7557)) +- **fix(sse):** feed compression pipeline the authoritative vision capability (#7237) ([#7560](https://github.com/diegosouzapw/OmniRoute/pull/7560)) +- **fix(dashboard):** providers model-name filter matches live/synced catalog (#7250) ([#7561](https://github.com/diegosouzapw/OmniRoute/pull/7561)) +- **fix(db):** pre-init sql.js WASM ahead of any getDbInstance() consumer (#7288) ([#7562](https://github.com/diegosouzapw/OmniRoute/pull/7562)) +- **fix(dashboard):** resolve costs page 500 from out-of-scope t() in TopListCard (#7272) ([#7564](https://github.com/diegosouzapw/OmniRoute/pull/7564)) +- **fix(dashboard):** surface rate-limit warning on 429 chat-probe (#7284) ([#7565](https://github.com/diegosouzapw/OmniRoute/pull/7565)) +- **fix(sse):** lazy-load playwright in claudeTurnstileSolver (#7265) ([#7566](https://github.com/diegosouzapw/OmniRoute/pull/7566)) +- **fix(sse):** combo failover for OpenAI streams truncated without finish_reason (#7285) ([#7568](https://github.com/diegosouzapw/OmniRoute/pull/7568)) +- **fix(cli):** reuse win32-aware locateCommand in tool-detector (#7279) ([#7569](https://github.com/diegosouzapw/OmniRoute/pull/7569)) +- **fix(codex):** #7536 check content-type before touching response.body in peek ([#7570](https://github.com/diegosouzapw/OmniRoute/pull/7570)) +- **fix(sse):** stop dropping tool_search and leaking OpenAI-only params in Responses->Chat translation ([#7571](https://github.com/diegosouzapw/OmniRoute/pull/7571)) +- **fix(api):** resolve provider display name and dedup byModel on normalized key (#7534, #7535) ([#7573](https://github.com/diegosouzapw/OmniRoute/pull/7573)) +- **fix(mitm):** route Claude Code standalone MITM traffic ([#7574](https://github.com/diegosouzapw/OmniRoute/pull/7574)) — thanks @dongwook-chan +- **fix(sse):** stop per-byte enumeration of binary image bytes in log redaction (#7297) ([#7576](https://github.com/diegosouzapw/OmniRoute/pull/7576)) +- **fix(sse):** split effort/reasoning suffix off pinned cursor model ids (#7289) ([#7577](https://github.com/diegosouzapw/OmniRoute/pull/7577)) +- **fix(chatgpt-web):** recognize update_content.messages[] celsius WS frames (#7357) ([#7578](https://github.com/diegosouzapw/OmniRoute/pull/7578)) +- **fix(sse):** 401 model-not-supported lockout + sticky quota-exhausted release (#7268, #7387) ([#7580](https://github.com/diegosouzapw/OmniRoute/pull/7580)) +- **fix(antigravity):** allow cloudcode envelope through messages guard ([#7582](https://github.com/diegosouzapw/OmniRoute/pull/7582)) — thanks @dongwook-chan +- **fix(sse):** sanitize empty-signature thinking blocks + hoist strict-provider system messages ([#7583](https://github.com/diegosouzapw/OmniRoute/pull/7583)) +- **fix(sse):** honor per-model targetFormat override for zai/glm-coding-apikey (#7364) ([#7584](https://github.com/diegosouzapw/OmniRoute/pull/7584)) +- **fix(sse):** clamp glm-4.6v max_tokens to the 32768 ceiling (#7364) ([#7585](https://github.com/diegosouzapw/OmniRoute/pull/7585)) +- **fix(cli):** log Codex Responses WebSocket history/usage per logical turn, not per connection ([#7588](https://github.com/diegosouzapw/OmniRoute/pull/7588)) +- **fix(providers):** derive static model catalogs for search providers from searchTypes ([#7589](https://github.com/diegosouzapw/OmniRoute/pull/7589)) +- **fix(stream-readiness):** bump timeout for heavy Claude-format reasoning replicas ([#7612](https://github.com/diegosouzapw/OmniRoute/pull/7612)) — thanks @herjarsa +- **fix(translator):** synthesize tool call chunks from response.completed batched output ([#7613](https://github.com/diegosouzapw/OmniRoute/pull/7613)) — thanks @ekinnee +- **fix(embeddings):** add lmstudio to embedding provider registry ([#7614](https://github.com/diegosouzapw/OmniRoute/pull/7614)) — thanks @ekinnee +- **fix(combo):** auto-clear stale session pins and emit recovery hints on combo exhaustion ([#7625](https://github.com/diegosouzapw/OmniRoute/pull/7625)) — thanks @herjarsa +- **fix(providers):** unify connection and routing flows ([#7629](https://github.com/diegosouzapw/OmniRoute/pull/7629)) — thanks @nguyenha935 +- **fix(db):** dedupe bulk-imported proxies by full credential tuple (#7594) ([#7644](https://github.com/diegosouzapw/OmniRoute/pull/7644)) — thanks @alltomatos +- **fix(api):** allow text-to-image on dual-modality models + revive HuggingFace image host ([#7648](https://github.com/diegosouzapw/OmniRoute/pull/7648)) — thanks @danscMax +- **fix(stryker):** add Microsoft Designer test to tap.testFiles ([#7659](https://github.com/diegosouzapw/OmniRoute/pull/7659)) +- **fix(dashboard):** cut UI import chain from connection persist module (CI shard base-red) ([#7677](https://github.com/diegosouzapw/OmniRoute/pull/7677)) + +- **fix(perplexity-web):** stop empty-content responses from live schematized SSE ([#6955](https://github.com/diegosouzapw/OmniRoute/pull/6955)) — thanks @artickc +- **fix(dashboard):** make quota cards container responsive ([#7027](https://github.com/diegosouzapw/OmniRoute/pull/7027)) — thanks @xz-dev +- **fix(nvidia):** restore GLM-5.2 reasoning on NIM (#7215) ([#7296](https://github.com/diegosouzapw/OmniRoute/pull/7296)) — thanks @backryun +- **fix(i18n):** complete Vietnamese dashboard localization and runtime fixes ([#7493](https://github.com/diegosouzapw/OmniRoute/pull/7493)) — thanks @nguyenha935 +- **fix(providers):** migrate muse-spark-web from GraphQL to WebSocket protocol ([#7528](https://github.com/diegosouzapw/OmniRoute/pull/7528)) — thanks @Ajeesh25353646 +- **fix(combo):** expose computed context_length via /api/combos for accurate OC plugin display ([#7633](https://github.com/diegosouzapw/OmniRoute/pull/7633)) — thanks @herjarsa +- **fix(api):** enumerate tiered auto combo endpoints in /api/combos/auto ([#7662](https://github.com/diegosouzapw/OmniRoute/pull/7662)) — thanks @ekinnee +- **fix(dashboard):** topology reflects connection health + clears finished requests ([#7672](https://github.com/diegosouzapw/OmniRoute/pull/7672)) — thanks @danscMax +- **fix(kimi-coding):** capture and replay reasoning for thinking-mode turns ([#7673](https://github.com/diegosouzapw/OmniRoute/pull/7673)) — thanks @xz-dev +- **fix(ci):** merge-train --fast mirrors test:unit subdir allowlist ([#7688](https://github.com/diegosouzapw/OmniRoute/pull/7688)) +- **fix(sse):** start credential-health sweep at boot so stale web sessions recover ([#7689](https://github.com/diegosouzapw/OmniRoute/pull/7689)) — thanks @danscMax +- **fix(cursor):** discover models via official CLI command ([#7692](https://github.com/diegosouzapw/OmniRoute/pull/7692)) — thanks @makcimbx +- **fix(quota):** fix antigravity/agy multi-model quota skipping in combos ([#7695](https://github.com/diegosouzapw/OmniRoute/pull/7695)) — thanks @irvandikky +- **fix(usage):** preserve account identity history ([#7700](https://github.com/diegosouzapw/OmniRoute/pull/7700)) — thanks @xz-dev +- **fix(db):** update proxies on password rotation ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- **fix(providers):** correct Chutes registry baseUrl (#7621) ([#7708](https://github.com/diegosouzapw/OmniRoute/pull/7708)) +- **fix(routing):** strip prompt_cache_key for NVIDIA NIM (#7617) ([#7709](https://github.com/diegosouzapw/OmniRoute/pull/7709)) +- **fix(providers):** degrade Arena (lmarena) cookie validation redirect to unsupported (#7542) ([#7710](https://github.com/diegosouzapw/OmniRoute/pull/7710)) +- **fix(claude-web):** unify Turnstile/executor/fast-path User-Agents behind one fingerprint (#7548) ([#7711](https://github.com/diegosouzapw/OmniRoute/pull/7711)) +- **fix(sse):** authenticate CLIProxyAPI fallback/passthrough legs with a dedicated credential (#7645) ([#7712](https://github.com/diegosouzapw/OmniRoute/pull/7712)) +- **fix(sse):** proactively refresh Grok Build OAuth token before dispatch (#7610) ([#7715](https://github.com/diegosouzapw/OmniRoute/pull/7715)) +- **fix(providers):** classify ambiguous Mistral 401 instead of hard auth error (#7638) ([#7718](https://github.com/diegosouzapw/OmniRoute/pull/7718)) +- **fix(security):** bump adm-zip >=0.6.0 + exact host matching in mitm DNS test ([#7732](https://github.com/diegosouzapw/OmniRoute/pull/7732)) +- **fix(icons):** fall back to Stepfun Mono when Color component is absent … ([#7743](https://github.com/diegosouzapw/OmniRoute/pull/7743)) — thanks @Dan-ex-hub +- **fix(stream):** suppress `` close marker for Responses API clients ([#7747](https://github.com/diegosouzapw/OmniRoute/pull/7747)) — thanks @xz-dev +- **fix(sse):** wire settings.wildcardAliases into model resolution (#7693) ([#7748](https://github.com/diegosouzapw/OmniRoute/pull/7748)) +- **fix(authz):** classify forge/jcode CLI settings routes as LOCAL_ONLY (#7263) ([#7749](https://github.com/diegosouzapw/OmniRoute/pull/7749)) +- **fix(routing):** honor eye-icon hidden models for no-auth providers in auto-combo (#7620) ([#7750](https://github.com/diegosouzapw/OmniRoute/pull/7750)) +- **fix(sse):** persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) ([#7751](https://github.com/diegosouzapw/OmniRoute/pull/7751)) +- **fix(docs):** heal release-green docs drift + eslint any-suppression drift (#7253) ([#7755](https://github.com/diegosouzapw/OmniRoute/pull/7755)) +- **fix(mcp):** copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) ([#7756](https://github.com/diegosouzapw/OmniRoute/pull/7756)) +- **fix(packaging):** move fumadocs-mdx to devDependencies (#7661) ([#7757](https://github.com/diegosouzapw/OmniRoute/pull/7757)) +- **fix(ci):** build API-only smoke workflows backend-only to fix dast-smoke timeouts (#7226) ([#7758](https://github.com/diegosouzapw/OmniRoute/pull/7758)) +- **fix(cli):** load DATA_DIR/server.env as fallback for .env on Electron migration (#7302) ([#7759](https://github.com/diegosouzapw/OmniRoute/pull/7759)) +- **fix(cli):** split outboundUrlGuard's DB helpers so setup-opencode packages cleanly (#7682) ([#7760](https://github.com/diegosouzapw/OmniRoute/pull/7760)) +- **fix(notion-web):** production-ready labels, multi-workspace, inference, usage (FINAL) ([#7768](https://github.com/diegosouzapw/OmniRoute/pull/7768)) — thanks @artickc +- **fix(kimi):** expose K3 reasoning effort levels ([#7776](https://github.com/diegosouzapw/OmniRoute/pull/7776)) — thanks @xz-dev +- **fix(compression):** apply compression combo assignments to routing combos ([#7779](https://github.com/diegosouzapw/OmniRoute/pull/7779)) — thanks @ekinnee +- **fix(i18n):** regenerate Polish UI locale from English ([#7782](https://github.com/diegosouzapw/OmniRoute/pull/7782)) — thanks @leszek3737 +- **fix(combo):** retry transient errors in pipeline strategy ([#7794](https://github.com/diegosouzapw/OmniRoute/pull/7794)) — thanks @AndrianBalanescu +- **fix(quality):** register nvidia-quota-phase1 and service-provider-plugin-registry in stryker tap.testFiles ([#7796](https://github.com/diegosouzapw/OmniRoute/pull/7796)) +- **fix(stream):** synthesize terminal finish_reason chunk when upstream omits it (#7800) ([#7804](https://github.com/diegosouzapw/OmniRoute/pull/7804)) — thanks @AndrianBalanescu +- **fix(plugins):** 5 bugs on the plugin path (3 Windows-only, 2 all-platform) ([#7806](https://github.com/diegosouzapw/OmniRoute/pull/7806)) — thanks @tmone +- **fix(cli):** register ESM alias resolver for @/ paths under global install ([#7808](https://github.com/diegosouzapw/OmniRoute/pull/7808)) — thanks @rafaumeu +- **fix(auth):** gate invalid-key check on isRequireApiKeyEnabled for embeddings and web-fetch (#7785) ([#7810](https://github.com/diegosouzapw/OmniRoute/pull/7810)) — thanks @AndrianBalanescu +- **fix(ci):** repair release regressions exposed by clean runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812)) — thanks @backryun +- **fix(rerank):** add voyage format adapter for request/response translation (#7809) ([#7813](https://github.com/diegosouzapw/OmniRoute/pull/7813)) — thanks @AndrianBalanescu +- **fix(antigravity):** attempt onboarding when projectId is empty (#5193 regression of #2541) ([#7815](https://github.com/diegosouzapw/OmniRoute/pull/7815)) — thanks @rafaumeu +- **fix(stream):** emit terminal SSE frames on mid-stream upstream failure (#7699) ([#7816](https://github.com/diegosouzapw/OmniRoute/pull/7816)) — thanks @AndrianBalanescu +- **fix(sse):** strip orphaned tool_use before antigravity/Vertex Claude dispatch (#7752) ([#7822](https://github.com/diegosouzapw/OmniRoute/pull/7822)) +- **fix(translator):** sanitize tool_result.tool_use_id symmetrically with tool_use.id (#7705) ([#7823](https://github.com/diegosouzapw/OmniRoute/pull/7823)) +- **fix(oauth):** require chatgptUserId agreement for Codex account dedup (#7737) ([#7825](https://github.com/diegosouzapw/OmniRoute/pull/7825)) +- **fix(db):** purge in-memory key-health state when a provider connection is deleted (#7740) ([#7826](https://github.com/diegosouzapw/OmniRoute/pull/7826)) +- **fix(compression):** keep a retrievable preamble instead of a bare CCR marker (#7746) ([#7827](https://github.com/diegosouzapw/OmniRoute/pull/7827)) +- **fix(db):** log fatal boot-time SQLite driver-cascade failure before propagating (#7773) ([#7828](https://github.com/diegosouzapw/OmniRoute/pull/7828)) +- **fix(docker):** repair tls-client-node native binary after --ignore-scripts (#7802) ([#7829](https://github.com/diegosouzapw/OmniRoute/pull/7829)) +- **fix(auth):** restore TICK_MS in tokenHealthCheck (ReferenceError on startup) ([#7830](https://github.com/diegosouzapw/OmniRoute/pull/7830)) +- **fix(cli):** fix Windows CLI detection false negatives (#7753, #7774) ([#7831](https://github.com/diegosouzapw/OmniRoute/pull/7831)) +- **fix(docs):** document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID (#7793) ([#7833](https://github.com/diegosouzapw/OmniRoute/pull/7833)) +- **fix(dashboard):** fix collapsed quota card session/weekly order (#7764) ([#7834](https://github.com/diegosouzapw/OmniRoute/pull/7834)) +- **fix(dashboard):** mirror connection-row action-icon spacing under RTL (#7680) ([#7835](https://github.com/diegosouzapw/OmniRoute/pull/7835)) +- **fix:** avoid cmd.exe spawn on Windows by using os.hostname() before execSync fallback ([#7841](https://github.com/diegosouzapw/OmniRoute/pull/7841)) — thanks @tientien17 +- **fix(usage):** harden account identity reconciliation ([#7843](https://github.com/diegosouzapw/OmniRoute/pull/7843)) — thanks @xz-dev +- **fix(cli):** use rundll32 instead of cmd.exe for Windows browser fallback in dashboard command ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7844)) — thanks @tientien17 +- **fix:** add native lifecycle-aware health endpoint ([#7852](https://github.com/diegosouzapw/OmniRoute/pull/7852)) — thanks @RaviTharuma +- **fix:** reserve chat admission before body parsing ([#7853](https://github.com/diegosouzapw/OmniRoute/pull/7853)) — thanks @RaviTharuma +- **fix:** bound quadratic session-dedup memory growth ([#7855](https://github.com/diegosouzapw/OmniRoute/pull/7855)) — thanks @RaviTharuma +- **fix(compression):** enable OmniGlyph for Claude Fable 5 ([#7863](https://github.com/diegosouzapw/OmniRoute/pull/7863)) — thanks @enjoyer-hub +- **fix(notion-web):** add browser fingerprint headers to reduce Cloudflare challenges ([#7864](https://github.com/diegosouzapw/OmniRoute/pull/7864)) — thanks @HassiyYT +- **fix(mitm):** gate Agent Bridge Repair on sudo password (#7836) ([#7865](https://github.com/diegosouzapw/OmniRoute/pull/7865)) — thanks @skutanjir +- **fix(rerank):** honor the connection's pinned proxy on rerank calls (#7350) ([#7867](https://github.com/diegosouzapw/OmniRoute/pull/7867)) +- **fix(compression):** skip CCR on tool outputs to preserve agent loop ([#7869](https://github.com/diegosouzapw/OmniRoute/pull/7869)) — thanks @herjarsa +- **fix(vision-bridge):** reroute auto/ prefix to vision model when images present ([#7871](https://github.com/diegosouzapw/OmniRoute/pull/7871)) — thanks @herjarsa +- **fix(opencode-plugin):** support separate management read token ([#7885](https://github.com/diegosouzapw/OmniRoute/pull/7885)) — thanks @RaviTharuma +- **fix(sse):** CC bridge loses OpenAI-format image input (OpenCode/Kilo/Cline → AgentRouter) ([#7888](https://github.com/diegosouzapw/OmniRoute/pull/7888)) +- **fix(combo):** strip boolean reasoning field for opencode-go providers ([#7891](https://github.com/diegosouzapw/OmniRoute/pull/7891)) — thanks @AndrianBalanescu +- **fix(notion-web):** accept OpenAI content-parts arrays in transcript ([#7896](https://github.com/diegosouzapw/OmniRoute/pull/7896)) — thanks @artickc +- **fix(notion-web):** reuse threadId across OpenAI multi-turn (no new chat each request) ([#7900](https://github.com/diegosouzapw/OmniRoute/pull/7900)) — thanks @artickc +- **fix(gemini):** strip OpenAI "strict" tool-schema keyword for Antigravity ([#7901](https://github.com/diegosouzapw/OmniRoute/pull/7901)) — thanks @Witroch4 +- **fix(antigravity):** collect native functionCall parts in SSE collector ([#7902](https://github.com/diegosouzapw/OmniRoute/pull/7902)) — thanks @Witroch4 +- **fix(sse):** recover invalid Anthropic thinking signatures once ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) — thanks @insoln +- **fix(resilience):** don't cool down accounts or trip the breaker on client aborts ([#7908](https://github.com/diegosouzapw/OmniRoute/pull/7908)) — thanks @insoln +- **fix(dashboard):** preserve quota cutoff drafts ([#7909](https://github.com/diegosouzapw/OmniRoute/pull/7909)) — thanks @hydraxman +- **fix(providers):** treat public-host 302 as valid in Gemini Web connection test (#7859) ([#7917](https://github.com/diegosouzapw/OmniRoute/pull/7917)) +- **fix(providers):** read reasoning_text in Claude-format response translator (#7856) ([#7919](https://github.com/diegosouzapw/OmniRoute/pull/7919)) +- **fix(dashboard):** safely render structured error objects in Request Logs detail (#7845) ([#7920](https://github.com/diegosouzapw/OmniRoute/pull/7920)) +- **fix(dashboard):** repair monaco deep import broken by 0.56 exports map (#7897) ([#7922](https://github.com/diegosouzapw/OmniRoute/pull/7922)) +- **fix(autostart):** adopt 9Router VBS startup to suppress console flash on Windows ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) — thanks @tientien17 +- **fix(translators):** normalize TitleCase tool names for non-Anthropic models ([#7926](https://github.com/diegosouzapw/OmniRoute/pull/7926)) — thanks @nramabad +- **fix(api):** resolve local provider models via dashboard catalog fallback ([#7927](https://github.com/diegosouzapw/OmniRoute/pull/7927)) — thanks @ekinnee +- **fix(auto):** pool accounts by provider model ([#7928](https://github.com/diegosouzapw/OmniRoute/pull/7928)) — thanks @adrianaryaputra +- **fix(perplexity-web):** multi-step empty content + advanced-quota cooldown ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- **fix(ccr):** resolve principal via OMNIROUTE_API_KEY env var on stdio MCP transport ([#7932](https://github.com/diegosouzapw/OmniRoute/pull/7932)) — thanks @ekinnee +- **fix(combo):** context-aware fallback ignores model_context_override ([#7933](https://github.com/diegosouzapw/OmniRoute/pull/7933)) — thanks @tmone +- **fix(i18n):** preserve remaining Vietnamese localization ([#7935](https://github.com/diegosouzapw/OmniRoute/pull/7935)) — thanks @nguyenha935 +- **fix(mitm):** gate Agent Bridge DNS and Trust Cert on sudo password (#7938) ([#7939](https://github.com/diegosouzapw/OmniRoute/pull/7939)) — thanks @skutanjir +- **fix(providers):** route iflytek/sparkdesk to Spark's OpenAI-compatible host ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- **fix(sse):** preserve parallel_tool_calls for GPT-5.6 delegation under Codex Responses Lite (#7821) ([#7957](https://github.com/diegosouzapw/OmniRoute/pull/7957)) +- **fix(providers):** copilot-m365-web fails loudly on empty turns + tier-aware enterprise invocation (#7858, #7870) ([#7958](https://github.com/diegosouzapw/OmniRoute/pull/7958)) +- **fix(providers):** treat unreliable web-cookie /models probe status as unsupported, not valid (#7857) ([#7959](https://github.com/diegosouzapw/OmniRoute/pull/7959)) +- **fix(api):** add amazon-q to the static model catalog (#7820) ([#7960](https://github.com/diegosouzapw/OmniRoute/pull/7960)) +- **fix:** parse Gemini 429 RetryInfo.retryDelay for model lockout (#7940) ([#7961](https://github.com/diegosouzapw/OmniRoute/pull/7961)) +- **fix(quality):** tolerate ESLint's trailing unpruned-suppressions text in validate-release-green (#7837) ([#7962](https://github.com/diegosouzapw/OmniRoute/pull/7962)) +- **fix(cli):** translate missing sqlite bindings error into actionable guidance (#7868) ([#7963](https://github.com/diegosouzapw/OmniRoute/pull/7963)) +- **fix(cli):** spawn opencode.cmd shim with shell:true on win32 (#7913) ([#7964](https://github.com/diegosouzapw/OmniRoute/pull/7964)) +- **fix(dashboard):** correct block-extra-Claude-usage toggle copy to match quarantine behavior (#7918) ([#7965](https://github.com/diegosouzapw/OmniRoute/pull/7965)) +- **fix(api):** classify /api/acp/agents as loopback-only (#7948) ([#7966](https://github.com/diegosouzapw/OmniRoute/pull/7966)) +- **fix(auth):** restore configurable HEALTHCHECK_BATCH_SIZE dropped by #7719 (#7875) ([#7970](https://github.com/diegosouzapw/OmniRoute/pull/7970)) +- **fix(test):** widen ratelimit-admission pollUntil deadline to 10s (#7842) ([#7971](https://github.com/diegosouzapw/OmniRoute/pull/7971)) +- **fix(pricing):** clarify disabled automatic sync status ([#7972](https://github.com/diegosouzapw/OmniRoute/pull/7972)) — thanks @RaviTharuma +- **fix(combo):** exempt content_filter from empty-content detection ([#7973](https://github.com/diegosouzapw/OmniRoute/pull/7973)) — thanks @HouMinXi +- **fix(embeddings):** support secure multimodal inputs ([#7978](https://github.com/diegosouzapw/OmniRoute/pull/7978)) — thanks @RaviTharuma +- **fix(resilience):** cap exactCooldownMs against maxCooldownMs (#7940) ([#7980](https://github.com/diegosouzapw/OmniRoute/pull/7980)) — thanks @ekinnee +- **fix(electron):** derive macOS Helper name from execPath to remove 2nd Dock icon (#7941) ([#8002](https://github.com/diegosouzapw/OmniRoute/pull/8002)) +- **fix(chatcore):** report string-reason client aborts as 499, not 502 (#7907) ([#8011](https://github.com/diegosouzapw/OmniRoute/pull/8011)) — thanks @Long-Feeds +- **fix(models):** drop generic catalog siblings of specialty surfaces (#8015) ([#8021](https://github.com/diegosouzapw/OmniRoute/pull/8021)) — thanks @RaviTharuma +- **fix(models):** stop inventing chat capabilities for specialty surfaces (#8016) ([#8022](https://github.com/diegosouzapw/OmniRoute/pull/8022)) — thanks @RaviTharuma +- **fix(capabilities):** resolve models.dev specialty rows across provider keys (#8017) ([#8023](https://github.com/diegosouzapw/OmniRoute/pull/8023)) — thanks @RaviTharuma +- **fix(models):** attach models.dev pricing to GET /v1/models entries (#8018) ([#8025](https://github.com/diegosouzapw/OmniRoute/pull/8025)) — thanks @RaviTharuma +- **fix(grok-cli):** require full auth.json on OAuth paste import (#7610) ([#8027](https://github.com/diegosouzapw/OmniRoute/pull/8027)) — thanks @RaviTharuma +- **fix(grok-cli):** sanitize function_call_output before Grok Build dispatch (#7611) ([#8030](https://github.com/diegosouzapw/OmniRoute/pull/8030)) — thanks @RaviTharuma +- **fix(sse):** bound forwarded response headers ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- **fix(sse):** replace spoofable .includes() PromptQL issuer check with hostname comparison (#8029) ([#8042](https://github.com/diegosouzapw/OmniRoute/pull/8042)) +- **fix(sse):** bound Codex SSE peek read with per-read timeout (#8020) ([#8043](https://github.com/diegosouzapw/OmniRoute/pull/8043)) +- **fix(cli):** stop double-prefixing combo model ids in opencode plugin static catalog (#7976) ([#8047](https://github.com/diegosouzapw/OmniRoute/pull/8047)) +- **fix(antigravity):** scope 404 model-not-found lockout to exact model + bare-model autopick ([#8050](https://github.com/diegosouzapw/OmniRoute/pull/8050)) — thanks @AndrianBalanescu +- **fix:** repair pre-existing red gates on the release/v3.8.49 tip ([#8055](https://github.com/diegosouzapw/OmniRoute/pull/8055)) +- **fix(oauth):** honor connectionId on token refresh so email-less providers don't duplicate ([#8062](https://github.com/diegosouzapw/OmniRoute/pull/8062)) — thanks @insoln +- **fix:** classify Google quota exhaustion responses ([#8071](https://github.com/diegosouzapw/OmniRoute/pull/8071)) — thanks @rafaumeu +- **fix(providers):** refresh duckduckgo-web catalog to current Duck.ai wire ids (#8000) ([#8079](https://github.com/diegosouzapw/OmniRoute/pull/8079)) +- **fix(security):** decouple request PII redaction from injection mode ([#8102](https://github.com/diegosouzapw/OmniRoute/pull/8102)) — thanks @RaviTharuma +- **fix(providers):** discover live AGY models ([#8123](https://github.com/diegosouzapw/OmniRoute/pull/8123)) — thanks @adevwithpurpose +- **fix(guardrails):** align INPUT_SANITIZER request masking gate (#8093) ([#8124](https://github.com/diegosouzapw/OmniRoute/pull/8124)) — thanks @RaviTharuma +- **fix(providers):** refresh Baidu ERNIE and Qianfan website URLs (#6271) ([#8128](https://github.com/diegosouzapw/OmniRoute/pull/8128)) — thanks @TrackCrewGalore +- **fix(stream):** add logging to empty catch blocks in stream error handling ([#8143](https://github.com/diegosouzapw/OmniRoute/pull/8143)) — thanks @chirag127 +- **fix(sse):** stop Codex/Responses sanitizer turning system image_url into output_text (#8089) ([#8147](https://github.com/diegosouzapw/OmniRoute/pull/8147)) +- **fix(db):** register SIGHUP handler and stop force-killing server on win32 stop paths (#8045) ([#8148](https://github.com/diegosouzapw/OmniRoute/pull/8148)) +- **fix(providers):** add missing poe registry baseUrl entry (#8082) ([#8149](https://github.com/diegosouzapw/OmniRoute/pull/8149)) +- **fix(routing):** anchor quota cache on globalThis for cross-chunk consistency (#8065) ([#8150](https://github.com/diegosouzapw/OmniRoute/pull/8150)) +- **fix(responses):** close namespace round-trip for Responses-Chat translation (#7936) ([#8151](https://github.com/diegosouzapw/OmniRoute/pull/8151)) — thanks @RCrushMe +- **fix(oauth):** warn instead of silently opening unreachable localhost redirect for LAN-IP Codex/xAI/Grok OAuth (#8046) ([#8152](https://github.com/diegosouzapw/OmniRoute/pull/8152)) +- **fix(db):** stop closing the sql.js singleton in getDbInstance() probe/reopen (#7494) ([#8153](https://github.com/diegosouzapw/OmniRoute/pull/8153)) +- **fix(sse):** run compression pipeline per turn in Codex Responses WS bridge (#8052) ([#8154](https://github.com/diegosouzapw/OmniRoute/pull/8154)) +- **fix(cli):** merge node bin dir into CLI healthcheck PATH for codex detection (#8036) ([#8156](https://github.com/diegosouzapw/OmniRoute/pull/8156)) +- **fix(sse):** anonymous fingerprint fallback for keyless Pollinations image gen (#8085) ([#8157](https://github.com/diegosouzapw/OmniRoute/pull/8157)) +- **fix(cli):** surface the real spawn error in process supervisor (#8091) ([#8158](https://github.com/diegosouzapw/OmniRoute/pull/8158)) +- **fix:** strip internal reasoning placeholder from user-visible content (#8081) ([#8162](https://github.com/diegosouzapw/OmniRoute/pull/8162)) — thanks @Dingding-leo +- **fix(combos):** expose synced reasoning-effort variants in Combo Builder model picker (#8072) ([#8165](https://github.com/diegosouzapw/OmniRoute/pull/8165)) — thanks @Dingding-leo +- **fix(windows):** add windowsHide to all child process spawns (#8131) ([#8167](https://github.com/diegosouzapw/OmniRoute/pull/8167)) — thanks @Dingding-leo +- **fix(cursor):** bridge native tools to client calls ([#8171](https://github.com/diegosouzapw/OmniRoute/pull/8171)) — thanks @makcimbx +- **fix(security):** bound JWT-extraction regexes to prevent polynomial ReDoS (CodeQL #754/#755/#756) ([#8173](https://github.com/diegosouzapw/OmniRoute/pull/8173)) +- **fix(#8141):** log pending request counter decrement failures ([#8179](https://github.com/diegosouzapw/OmniRoute/pull/8179)) — thanks @rafaumeu +- **fix(#8135):** suppress sql.js build warning via non-analyzable dynamic import ([#8184](https://github.com/diegosouzapw/OmniRoute/pull/8184)) — thanks @rafaumeu +- **fix(#8093):** align INPUT_SANITIZER_ENABLED default to true across all docs ([#8185](https://github.com/diegosouzapw/OmniRoute/pull/8185)) — thanks @rafaumeu +- **fix(combo):** skip remaining same-provider targets on 401/403 auth failure ([#8195](https://github.com/diegosouzapw/OmniRoute/pull/8195)) — thanks @rafaumeu +- **fix(compression):** make memo key model-independent for non-vision engines ([#8196](https://github.com/diegosouzapw/OmniRoute/pull/8196)) — thanks @rafaumeu +- **fix(resilience):** add max/step to NumberField for provider cooldown inputs (#8107) ([#8203](https://github.com/diegosouzapw/OmniRoute/pull/8203)) — thanks @rafaumeu +- **fix(providers):** fix Azure AI Foundry multi-model discovery and per-deployment connection testing (#8174) ([#8206](https://github.com/diegosouzapw/OmniRoute/pull/8206)) — thanks @not-knope +- **fix(logs):** stop the async-EPIPE log-flood loop at its ignition point ([#8207](https://github.com/diegosouzapw/OmniRoute/pull/8207)) — thanks @Tasogarre +- **fix(sse):** surface OpenRouter mid-stream error chunks instead of a false empty success ([#8210](https://github.com/diegosouzapw/OmniRoute/pull/8210)) — thanks @hartmark +- **fix(sse):** Gemini malformed function-call handling + tool_choice translation ([#8211](https://github.com/diegosouzapw/OmniRoute/pull/8211)) — thanks @hartmark +- **fix(sse):** tool-incapable provider handling (AI Horde + Responses content-collapse scoping) ([#8212](https://github.com/diegosouzapw/OmniRoute/pull/8212)) — thanks @hartmark +- **fix(sse):** Gemini TPM/RPD quota classification + combo cooldown-wait resilience ([#8213](https://github.com/diegosouzapw/OmniRoute/pull/8213)) — thanks @hartmark +- **fix(services):** resolve and record a real pid when adopting a service ([#8218](https://github.com/diegosouzapw/OmniRoute/pull/8218)) — thanks @seanford +- **fix(memory):** resolve remote embedding dimensions for reindex (#8074) ([#8220](https://github.com/diegosouzapw/OmniRoute/pull/8220)) — thanks @Prudhvivuda +- **fix(dashboard):** correct machine-translated Korean UI strings in ko.json ([#8224](https://github.com/diegosouzapw/OmniRoute/pull/8224)) — thanks @MichaelYcJo +- **fix(devin-cli):** refresh shared model catalog ([#8227](https://github.com/diegosouzapw/OmniRoute/pull/8227)) — thanks @backryun +- **fix(claude-web):** align session transport and fallback ([#8230](https://github.com/diegosouzapw/OmniRoute/pull/8230)) — thanks @backryun +- **fix:** restore OAuth auto-refresh for gemini-cli connections ([#8232](https://github.com/diegosouzapw/OmniRoute/pull/8232)) — thanks @seanford +- **fix:** normalize Codex URLs and dashboard regressions ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- **fix(api):** narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) ([#8236](https://github.com/diegosouzapw/OmniRoute/pull/8236)) +- **fix(gemini):** drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) ([#8238](https://github.com/diegosouzapw/OmniRoute/pull/8238)) +- **fix(backend):** word-boundary-safe tool-result truncation in lite compression mode (#8169) ([#8239](https://github.com/diegosouzapw/OmniRoute/pull/8239)) +- **fix(providers):** filter unsupported family-fallback candidates against the provider catalog (#8134) ([#8240](https://github.com/diegosouzapw/OmniRoute/pull/8240)) +- **fix(translator):** synthesize tool call chunks from `response.completed` batched output when upstream omits individual `output_item.added`/`done` events, fixing `finish_reason: "stop"` instead of `"tool_calls"` for agentic clients ([#180](https://github.com/diegosouzapw/OmniRoute/issues/180), [#3980](https://github.com/diegosouzapw/OmniRoute/issues/3980)) +- **fix(api):** Vercel Relay deploy now checks the Deployment Protection (SSO) PATCH response and surfaces `ssoProtectionWarning` when Vercel rejects it, instead of silently activating a relay that later returns an undiagnosed `403 Access denied`. (thanks @ricatix) ([#1037](https://github.com/diegosouzapw/OmniRoute/issues/1037)) +- **fix(oauth):** resolve Kiro AWS SSO cache client credentials by matching the token's own `clientId` (including tokens with a direct `clientId` field instead of `clientIdHash`) instead of a region/latest-expiry guess, fixing spurious "Bad credentials" on refresh when multiple stale SSO client registrations are cached (thanks @XCrag). +- **fix(combo):** streaming Claude responses whose content block opens (`content_block_start`) and closes with no usable text/tool_use — a shape some upstreams return for tool-heavy requests on HTTP 200 — are now detected by `validateResponseQuality`'s SSE peek and trigger combo failover instead of being forwarded to the client as a silent empty completion (thanks @heishen6). ([#1382](https://github.com/diegosouzapw/OmniRoute/issues/1382)) +- **fix(codex):** strip regex `pattern` lookaround (lookahead/lookbehind) from tool JSON Schemas on the Codex/OpenAI native passthrough path — previously only the translated-request path coerced tool schemas, so a `pattern` like `^(?=.*@).+$` reached OpenAI unmodified and was rejected with `regex lookaround is not supported`. (thanks @evinjohnn) (#7100) +- **fix(cli):** `stopMitm()` now removes /etc/hosts DNS-spoof entries before killing the MITM server process, closing the window where a client's DNS still resolved a target host to `127.0.0.1` while nothing was listening there — the cause of `connect ECONNREFUSED 127.0.0.1:443` right after stopping the MITM proxy (thanks @dionisius95). +- **fix(sse):** Cursor Composer/Auto tool calls that separate the arg name and value with a space instead of a newline (e.g. `path /Users/.../test`) no longer produce empty-valued, malformed argument keys, fixing silent no-op Write/tool calls. (thanks @way-art) +- **fix(dashboard):** the "Custom Models" add/edit form now has a "Vision capable" toggle so a custom OpenAI-compatible model can be manually flagged as vision-capable when the provider's discovery metadata doesn't report an image input modality (thanks @nguyenphi37) +- **fix(combos):** fusion combos now reject an oversized panel (>40 models by default, tunable via `fusionTuning.maxPanel`) with a clean 400 before fanning out, instead of buffering dozens of concurrent full responses in memory and OOM-crashing the whole container. (thanks @fontvu) +- **fix(providers):** the OpenAI-compatible "Check" validation flow now surfaces a warning when the chat-completions probe returns `404` (e.g. `model_not_found`) instead of silently passing as `Valid` — a bogus/non-standard model id (Featherless/OpenRouter-style `vendor/model` typos) previously went undetected at Check time and only surfaced once a real request tripped the per-model lockout. (thanks @advane204f) +- **fix(dashboard):** include never-tested custom provider connections in the combo builder's active-provider list so their models load without requiring a manual connection test first. (thanks @fajarbossit) +- **fix(executors):** forward agent-supplied `X-Session-ID`/`X-Title` metadata headers to upstream providers — previously dropped for every client outside the `x-opencode-*` allowlist. (thanks @chitholian) (#7104) +- **fix(sse):** Antigravity streaming requests that hit a non-ok upstream response (e.g. a 403) no longer pipe the raw upstream bytes straight through to the client — a binary/non-UTF8 error body (observed as gzip-magic-byte garbage) is now routed through the same sanitized `buildAntigravityUpstreamError()` path the non-streaming branch already used, instead of corrupting the client-visible error message. Regression guard: `tests/unit/antigravity-streaming-error-body-sanitized-2461.test.ts` — thanks @Duongkhanhtool +- **fix(providers):** MiniMax Text-to-Image now works — a `minimax` image-generation provider (`minimax-image` format, `image-01`/`image-01-live` models) was registered, since MiniMax previously had entries in the music/audio/video registries but none in the image registry, so any MiniMax image-model request fell through to a 404/unmatched-format response. (thanks @felipeleite) +- **fix(cli):** the runtime self-heal now verifies a cached `better-sqlite3` native binary actually loads for the running Node before trusting it — the old check only inspected the file's magic bytes (ELF/Mach-O/PE header), so a binary built for a different Node ABI passed validation and segfaulted the process on first use instead of triggering a rebuild. (thanks @mrprohack) (#7105) ([#2493](https://github.com/diegosouzapw/OmniRoute/issues/2493)) +- **fix(openai):** strip `reasoning_effort`/`reasoning` for GPT-5.x models on the raw `openai` Chat Completions surface when the request carries function `tools` — upstream rejects that combination with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"), and the dashboard has no `reasoning_effort:"none"` override to work around it client-side — thanks @techsolutionmta +- fix(providers): preserve relayAuth for vercel/deno/cloudflare relay proxies referenced by-id from the no-auth-provider Proxy Pool dropdown (#5716) +- fix(providers): wire the Devin cloud-agent provider into the generic provider-page validator and static model catalog, matching the existing `jules` cloud-agent pattern (#6142) +- **fix(providers):** refresh Baidu ERNIE + Qianfan provider website URLs to current developer landing pages ([#6271](https://github.com/diegosouzapw/OmniRoute/issues/6271)) — thanks @TrackCrewGalore +- fix(providers): honor a provider-level proxy assigned to no-auth providers like MiMoCode Free (#6272) +- fix(api): merge tool_call continuation deltas that carry only `id` (no `index`) so tool-call arguments are no longer split/lost in request/response logs (#6276) +- **fix(providers):** modernize the `lmarena` provider for the Arena.ai rebrand — route chat through `arena.ai` create-evaluation with Chrome TLS impersonation, seed a static Direct-chat Text/Search + Image catalog, and keep the `lmarena`/`lma` wire id for back-compat ([#6280](https://github.com/diegosouzapw/OmniRoute/pull/6280)) — thanks @backryun +- **fix(providers):** web-provider model discovery updated — qwen-web uses the slash-terminated models endpoint (avoiding a blocked 307 redirect), and kimi-web matches the current request shape (POST with bearer + `kimi-auth` cookie replay) with its catalog refreshed to the current non-agent models (#6308 — thanks @janeza2). +- **fix(logs):** the request-log detail modal no longer reopens by itself after being closed — a stale in-flight detail refresh resolved after close and re-triggered the modal open state (#6323 — thanks @xz-dev). +- **fix(providers):** update SenseNova Token Plan support — register the token-plan model ids/constants and adjust the SenseNova registry so token-plan accounts route correctly (#6330 — thanks @xz-dev). +- fix(providers): give v0-vercel-web its own alias so its credentials are detected (#6343) +- fix(providers): route AgentRouter key validation through the CC wire image so a valid key no longer 403s as "Invalid API key" (#6377) +- fix(db): stop legacy log-archive migration from deleting the live app-logger directory and crashing startup on a stat/stream race (#6401, #6799) +- fix(docs): document Turbopack build memory tradeoff and `OMNIROUTE_USE_TURBOPACK=0` webpack fallback for RAM-constrained machines (#6409) +- fix(compression): surface silently-dropped stacked-pipeline steps (session-dedup, ccr) and stop the aggregate inflation guard from misfiring on a genuine no-op (#6479, #6480, #6491) +- fix(providers): honor the `max_token` capability override in the reasoning-token-buffer output cap (#6524) +- **fix(dashboard):** the onboarding tier-flow diagram rendered broken — its SVGs lived in the repo-root `images/` (not a served path); moved to `public/images/` so Next.js serves them (#6538 — thanks @ianriizky). +- **fix(routing):** the `auto` combo's no-auth candidate pool now honors a disabled provider connection's own `isActive=false` (the toggle on the main Providers grid card), not just the separate global `blockedProviders` setting — disabling opencode/mimocode/etc. via the grid toggle no longer leaves it in rotation ([#6557](https://github.com/diegosouzapw/OmniRoute/issues/6557)). +- **fix(sse):** server-tool literal names (e.g. `web_search`) are preserved in message history and `tool_choice` instead of being namespaced/rewritten, so follow-up turns referencing those tools keep working (#6586 — thanks @MikeTuev). +- fix(sse): sanitize non-Latin1 characters before embedding combo diagnostics in HTTP headers, preventing a ByteString crash on quality-check failure (#6612) +- fix(api): recognize OpenRouter reasoning/reasoning_details in non-streaming OpenAI-to-Claude conversion (#6623) +- fix(db): share one in-flight sql.js load across concurrent `preInitSqlJs()` callers to stop the boot-time thundering-herd re-decode of the whole database file (#6628) +- fix(db): unwrap lone named-parameter objects before `sql.js` `stmt.bind()` so `@`/`:`/`$`-style named placeholders bind correctly instead of throwing "Wrong API use" (#6802) +- **fix(db): break probe-failed/restore loop on large storage.sqlite** (#6632 — thanks @KooshaPari). +- fix(ci): exclude check-test-masking.test.ts's own tautology fixtures from the diff-based test-masking gate and recognize `✗` in validate-release-green's failure-line detector (#6634) +- fix(routing): recognize Kimi-style "exceeded model token limit" 400 as context overflow so combo fallback continues to the next target (#6637) +- **fix(cli):** Claude Code installed via WinGet is now detected on Windows (the WinGet install path was missing from the binary lookup) (#6647 — thanks @enjoyer-hub). +- **fix(providers):** removed obsolete/defunct providers from the catalog (glhf, kluster, cablyai, inclusionai) (#6675 — thanks @backryun). +- **fix(sse):** requests rejected before `handleChatCore` (circuit-breaker/cooldown gate or combo with all targets exhausted) are now recorded in `usage_history` too, so a key whose traffic was entirely gate-rejected no longer shows "zero requests" in the per-API-key usage counter (#6698). +- fix(providers): reject chat-completions requests for cloud-agent-only providers like jules instead of silently mis-routing them to OpenAI's endpoint (#6699) +- **fix(sse):** unwrap bare `{function:{…}}` tools so OpenAI-shape clients no longer have tools silently dropped in Claude translation. (thanks @samir-abis) +- **fix(oauth):** stop merging distinct Codex OAuth logins that share an email but lack a verifiable account id, preventing silent token overwrite. (thanks @lucasjustinudin) +- **fix(codex):** detect "model at capacity"/overloaded errors embedded in a 200-OK SSE stream and surface them as a real error so account fallback rotates, instead of passing them through as a successful response. (thanks @ryanngit) +- **fix(volcengine):** clamp `max_tokens` to the VolcEngine Ark endpoint cap for the Kimi model so oversized values no longer 400. (thanks @whale9820) +- **fix(antigravity):** surface aborted/malformed Gemini tool calls (e.g. `MALFORMED_FUNCTION_CALL`) as an explicit non-`end_turn` finish reason instead of a silent clean completion. (thanks @anhdiepmmk) +- **fix(routing):** the reasoning-token headroom buffer clamps to the model's explicit output cap instead of inflating past it, and `getExplicitModelOutputCap` falls through to the registry/spec cap when a synced capability row exists without a numeric `limit_output` ([#6714](https://github.com/diegosouzapw/OmniRoute/pull/6714)) — thanks @xz-dev +- **fix(api):** `omniroute health` (and `health components`/`health watch`) returned `Error: HTTP 404` ([#6677](https://github.com/diegosouzapw/OmniRoute/issues/6677)) — `bin/cli/commands/health.mjs` called `apiFetch("/api/health", ...)`, a route that was moved to `GET /api/monitoring/health` (`src/app/api/monitoring/health/route.ts`) without updating the CLI; `src/app/api/health/` on disk only has `degradation/route.ts` and `ping/route.ts`, no top-level handler. `runHealthCommand()`/`runHealthComponentsCommand()` now call `/api/monitoring/health` and read its actual payload shape (`activeConnections`, `circuitBreakers: {open, halfOpen, closed}`, `memoryUsage`) instead of the old, nonexistent `requests`/`breakers`/`cache`/`memory` fields. Regression guard: `tests/unit/cli-health-monitoring-route.test.ts`. ([#6717](https://github.com/diegosouzapw/OmniRoute/pull/6717)) +- **fix(startup):** webpack build broke on case-insensitive filesystems (macOS APFS default, Windows) with a casing-collision warning plus "not exported" errors in `StudioConfigPane.tsx`/`ChatTab.tsx` (#6584) — `src/app/(dashboard)/dashboard/playground/components/ReasoningControls.tsx` (the component) and `reasoningControls.ts` (the utils module) shared the same lower-cased stem in the same directory, and two importers used the extensionless form `from "./reasoningControls"`, the exact resolution path that becomes ambiguous once casing is folded. Renamed the utils module to `reasoningControlUtils.ts` (no collision) and updated the 3 import sites. Regression guard: `tests/unit/case-collision-6584.test.ts` (scans `src/`/`open-sse/` for any same-directory, case-only filename collision). (#6584) ([#6718](https://github.com/diegosouzapw/OmniRoute/pull/6718)) +- **fix(build):** Turbopack production build emitted an "Overly broad patterns can lead to build performance issues" warning per entry point importing `src/lib/agentSkills/generator.ts` (603 warnings reported on v3.8.46, up from 379 on v3.8.45) ([#6582](https://github.com/diegosouzapw/OmniRoute/issues/6582)) — `generator.ts`'s `outputBase` is built as `path.isAbsolute(outputDir) ? outputDir : path.join(process.cwd(), outputDir)`, where `outputDir` is a runtime function parameter, not a compile-time literal, so Turbopack's build-time file-tracing analyzer can't statically narrow the several dynamic `readdirSync`/`rmSync`/`readFileSync`/`writeFileSync` call sites a few lines below and falls back to a project-wide glob; #6366's commit message claimed to "anchor the base path with a literal" but the shipped code never did. Since this fs access is legitimate and bounded (`skills//SKILL.md`, ~48 known IDs), `next.config.mjs`'s `turbopack.ignoreIssue` (Next.js 16.2+) now suppresses this specific, known-benign diagnostic, mirroring the existing `webpack.ignoreWarnings`/`isNextIntlExtractorDynamicImportWarning` precedent already in the same file for the webpack path. Regression guard: `tests/unit/next-config.test.ts` (asserts the `turbopack.ignoreIssue` rule shape targeting `src/lib/agentSkills/**`). ([#6720](https://github.com/diegosouzapw/OmniRoute/pull/6720)) +- **fix(providers):** Codex Desktop requests to `gpt-5.3-codex-spark` failed with `[400]: Tool 'image_generation' is not supported with gpt-5.3-codex-spark`, even on paid-plan accounts ([#6651](https://github.com/diegosouzapw/OmniRoute/issues/6651)) — `CodexExecutor.transformRequest` (`open-sse/executors/codex.ts`) only dropped the Codex Desktop-injected `image_generation` hosted tool when `isCodexFreePlan()` matched the account's plan, with no awareness that Spark-scope Codex models reject `image_generation` upstream regardless of plan. `dropImageGeneration` now also drops it when `getCodexModelScope(model) === "spark"` (the existing Spark classifier from `open-sse/config/codexQuotaScopes.ts`), independent of account plan. Regression guard: `tests/unit/codex-spark-image-generation.test.ts` (thanks @alltomatos for independently catching and fixing it via #6819). ([#6721](https://github.com/diegosouzapw/OmniRoute/pull/6721)) +- **fix(providers):** the provider quota card's weekly/session bars re-sorted by remaining percentage instead of staying in a fixed, deterministic order ([#6687](https://github.com/diegosouzapw/OmniRoute/issues/6687)) — `QuotaCardExpanded.tsx`'s `sortQuotasByRemaining()` (added in #5977) was applied unconditionally via `useMemo(() => sortQuotasByRemaining(quotas), [quotas])`, undoing the deterministic `CODEX_QUOTA_ORDER`/`GLM_QUOTA_ORDER` window order `quotaParsing.ts`'s `sortCodexOrder()`/`sortGlmOrder()` (added in #6336) already established for Codex and the GLM family — since #6336 never touched `QuotaCardExpanded.tsx`, the two orderings never composed, so e.g. a Codex `session` window with less headroom than `weekly` rendered after it instead of staying first. A new `hasFixedQuotaOrder()` (`quotaParsing.ts`) and `resolveQuotaDisplayOrder()` (`QuotaCardExpanded.tsx`) now skip the remaining-% re-sort for providers with a fixed window order, threading `providerId` from `QuotaCard.tsx` through to the display layer; every other provider still gets the remaining-% sort. Regression guard: `tests/unit/quota-card-expanded-fixed-order-6687.test.ts`. ([#6722](https://github.com/diegosouzapw/OmniRoute/pull/6722)) +- **fix(i18n):** pt-BR was missing 194 UI keys present in `en.json` — a real, silent data-sync gap, not covered by any duplicate/mislabeled #6694 (that issue's 9 `providers.*` keys are disjoint, present-but-untranslated sentinels caused by a separate `providerText()` fallback bug) ([#6695](https://github.com/diegosouzapw/OmniRoute/issues/6695)) — `scripts/i18n/sync-ui-keys.mjs` (which mirrors newly-added `en.json` keys into every locale) wasn't re-run after recent `en.json` additions, and the CI `i18n:check-ui-coverage` gate only fails a locale below an 80% threshold, so pt-BR stayed green at 93.8% coverage despite the gap. Backfilled all 194 missing keys into `src/i18n/messages/pt-BR.json` (translated to Brazilian Portuguese, no leftover `__MISSING__` markers) via `npm run i18n:sync-ui -- --locale=pt-BR` + manual translation. Regression guard: `tests/unit/i18n-pt-br.test.ts` (new case asserting full `en.json`→`pt-BR.json` key parity, so a future drift fails a fast unit test instead of silently degrading the coverage percentage). ([#6723](https://github.com/diegosouzapw/OmniRoute/pull/6723)) +- **fix(startup):** `omniroute --mcp` crashed at Node ESM link time with `ERR_MODULE_NOT_FOUND` for `ioredis` on installs where the published MCP bundle didn't happen to have `ioredis` rescued from a parent `node_modules` ([#6559](https://github.com/diegosouzapw/OmniRoute/issues/6559)) — `src/shared/utils/rateLimiter.ts` had a top-level static `import Redis from "ioredis"`; that module is only ever reached via a lazy `await import(...)` several call-sites deep in the MCP tool chain, but esbuild's `--packages=external` bundling of the MCP server (`scripts/build/prepublish.ts` Step 8.5) still hoisted rateLimiter.ts's own static import into a real top-level ESM import in the compiled `dist/open-sse/mcp-server/server.js`, forcing Node to resolve `ioredis` at module-link time — before any `--mcp` startup code runs — and `ioredis` is not guaranteed to ship in the MCP-only bundle's `node_modules`. `getRedisClient()` now lazily imports `ioredis` on first use (matching the established soft-dependency pattern in `src/lib/quota/redisQuotaStore.ts`) while still throwing synchronously when Redis isn't configured. Regression guard: `tests/unit/build/mcp-bundle-no-eager-ioredis.test.ts` (bundles the real MCP server entrypoint with the exact publish-time esbuild flags and asserts no top-level static `ioredis` import remains, while the pre-existing lazy `await import("ioredis")` in `redisQuotaStore.ts` stays intact). ([#6725](https://github.com/diegosouzapw/OmniRoute/pull/6725)) +- **fix(providers):** Kiro sent the adaptive-thinking `additionalModelRequestFields` envelope for `claude-sonnet-4.5`/`claude-haiku-4.5`, which Kiro/CodeWhisperer rejects upstream with a raw `[400]: additionalModelRequestFields is not supported for this model` ([#6576](https://github.com/diegosouzapw/OmniRoute/issues/6576)) — `buildKiroPayload()` (`open-sse/translator/request/openai-to-kiro.ts`) gated the field on the generic Anthropic-API `supportsReasoning()` capability flag, which is `true` for both models on Anthropic's direct API but does not reflect what Kiro's CodeWhisperer backend actually accepts; only `claude-sonnet-5` is confirmed adaptive-thinking-capable there. A new Kiro-specific allowlist (`supportsKiroAdaptiveThinking()` in `open-sse/translator/request/openai-to-kiro/adaptiveThinking.ts`) now gates the envelope instead. Regression guard: `tests/unit/repro-6576-kiro-thinking-unsupported-model.test.ts`. ([#6726](https://github.com/diegosouzapw/OmniRoute/pull/6726)) +- **fix(translator):** Cursor's local **Subagent** tool call is no longer rejected with `cloud_base_branch may only be specified when environment equals cloud` — the Responses→Chat tool-arg cleanup (`stripEmptyOptionalToolArgs`) was scoped to Claude Code's `Read` tool only, so Cursor's `Subagent` tool passed through with the cloud-only `cloud_base_branch: ""` (Cursor treats an empty string as "specified" and rejects the call before starting the local subagent). The cleanup now covers an allowlist of `Read` + `Subagent`; arbitrary tools are still left untouched (empty strings/arrays can be valid payloads for them). Regression guard: `tests/unit/openai-responses-subagent-strip-2446.test.ts`. (thanks @like3213934360-lab) +- **fix(translator):** GLM 5.2 (and other OpenAI-compatible upstreams that stream a tool call's `id` and `function.name` in **separate** SSE chunks) no longer produce an empty tool name / `No such tool available:` error through the Claude `/messages` path — the `openai-to-claude` streaming translator emitted `content_block_start` immediately on the id-only chunk with an empty `name`, and the Claude SSE protocol cannot patch a block after it is emitted, so the later name-only chunk was silently dropped. It now **defers** `content_block_start` until the tool name arrives (falling back to starting the block when arguments arrive first), so the emitted `tool_use` always carries the real name. Regression guard: `tests/unit/openai-to-claude-glm-split-tool-name-2077.test.ts`. (thanks @itiwant) +- **fix(resilience):** OmniRoute didn't respect an exhausted Ollama Cloud (or any other apikey-category provider) quota — it retried the account seconds later instead of waiting out the real reset window ([#6638](https://github.com/diegosouzapw/OmniRoute/issues/6638)) — `shouldPreserveQuotaSignalsFor429()`/`checkFallbackError()` (`open-sse/services/accountFallback.ts`) only applied body-text quota classification (daily/monthly/weekly quota-exhausted detection) to OAuth-category providers; apikey-category 429s (Ollama Cloud, OpenAI, etc.) always fell through to the generic short rate-limit cooldown regardless of what the error body said, and `parseRetryFromErrorText()` also had no support for day-granularity reset hints ("Your quota will reset in 3 days.") — only Xh/Ym/Zs combos. An explicit quota-exhausted signal in the body (`looksLikeQuotaExhausted()`) now overrides the apikey-category default via the new `shouldPreserveQuotaSignals()` (`open-sse/services/quotaResetParsing.ts`), and `parseDayGranularityResetMs()` parses whole-day reset countdowns so the real multi-day window is honored instead of a few seconds of backoff. Regression guard: `tests/unit/issue-6638-ollama-quota.test.ts` + 2 aligned `tests/unit/account-fallback-service.test.ts` cases that previously asserted the buggy rate_limit_exceeded/undefined-dailyQuotaExhausted behavior for apikey-provider quota text. ([#6731](https://github.com/diegosouzapw/OmniRoute/pull/6731)) +- **fix(resilience):** a combo step "pinned" to one fingerprint account (mimocode/mcode/opencode multi-account providers) never actually resolved to that account, so it couldn't fail over when the pinned account was depleted ([#6696](https://github.com/diegosouzapw/OmniRoute/issues/6696), relates #6612) — the combo builder UI encodes an account pin as a composite connectionId (`${rowId}|fp|${fingerprint}`, `src/lib/combos/builderOptions.ts`), but `expandTargetsByFingerprints()` (`open-sse/services/combo/fingerprintExpansion.ts`) looked that composite string up directly in `connectionById` (keyed by real DB row ids), got `undefined`, and passed the target through unchanged, still carrying the bogus composite id — so downstream credential resolution could never match it either. `expandTargetsByFingerprints()` now splits the `|fp|` composite id back into the real connection row id + the pinned fingerprint (new `splitFingerprintPin()` helper) before any lookup, resolving the target to the real connectionId (with the pinned fingerprint carried on the new `pinnedFingerprint` field) instead of the inert composite string. Regression guard: `tests/unit/combo-fingerprint-pin-6696.test.ts`. ([#6732](https://github.com/diegosouzapw/OmniRoute/pull/6732)) +- **fix(api):** Responses passthrough emitted event-only SSE frames (no `data:` line) for every dropped commentary event, breaking the OpenAI Python SDK's `sse.json()` parser ([#6561](https://github.com/diegosouzapw/OmniRoute/issues/6561)), follow-up to #6199/#6232 — the commentary-drop `continue;` branches in `open-sse/utils/stream.ts` skipped the `data:` line for a dropped commentary event but never cleared the already-buffered `event:` line for that same frame, so the next blank line flushed the stale `event:` line alone. Both drop sites now call `clearPendingPassthroughEvent()` before `continue`, discarding the buffered prefix along with the dropped payload; the commentary-drop decision itself was extracted into a new `open-sse/utils/responsesCommentaryDrop.ts` so the fix does not grow the frozen `stream.ts`. Regression guard: `tests/unit/responses-commentary-event-frame-6561.test.ts` (realistic `event:\ndata:\n\n` frames — the existing #6199 test only used bare `data:` lines and never exercised this path). ([#6735](https://github.com/diegosouzapw/OmniRoute/pull/6735)) +- **fix(compression):** `/api/compression/preview`'s top-level `originalTokens`/`compressedTokens` diverged from `engineBreakdown[0]`'s counts for the same single-engine run (tiktoken outer counts vs the `JSON.stringify(...).length/4` estimate per engine), worst on small inputs. A new `reconcileSingleEngineTokens()` overwrites the single-engine breakdown entry with the outer, more accurate figures; multi-step pipeline breakdowns are left untouched ([#6488](https://github.com/diegosouzapw/OmniRoute/issues/6488)). Regression guard: `tests/unit/compression/preview-outer-engine-token-reconcile-6488.test.ts`. ([#6741](https://github.com/diegosouzapw/OmniRoute/pull/6741)) +- **fix(resilience):** account selection could pick an account already out of quota upstream on every credentialed route except `chat`/`codex` ([#6686](https://github.com/diegosouzapw/OmniRoute/issues/6686)) — `getProviderCredentials()` (`src/sse/services/auth.ts`) only skips a connection when a *local cache* already flags it exhausted (`isQuotaExhaustedForRequest`/`src/domain/quotaCache.ts`); it never itself calls the registered upstream `QuotaFetcher`. Only `getProviderCredentialsWithQuotaPreflight()` performs that live upstream check, and it was wired into exactly 2 call sites (`src/sse/handlers/chat.ts`, `src/app/api/internal/codex-responses-ws/route.ts`) — every other credentialed route (`rerank`, `images/generations`, `images/edits`, `audio/transcriptions|speech|translations`, `videos/generations`, `music/generations`, `ocr`, `providers/[provider]/embeddings`, `providers/[provider]/images/generations`, `web/fetch`, `moderations`, `search`) called the plain, cache-only selector, so an account whose cache entry was never populated (e.g. its first request landed on one of these routes) could be selected even at 0% quota remaining. Those 14 call sites now go through `getProviderCredentialsWithQuotaPreflight()` instead, matching chat/codex coverage. Regression guard: `tests/unit/issue-6686-quota-preflight-coverage.test.ts` (static check that none of the routes call the plain selector anymore + a behavioral check that the preflight-aware selector blocks a 100%-used account). ([#6742](https://github.com/diegosouzapw/OmniRoute/pull/6742)) +- **fix(api):** `reasoning_content` (extended-thinking text) was silently dropped from `/v1/chat/completions` SSE on the `claude-web` and `v0-vercel-web` executors ([#6662](https://github.com/diegosouzapw/OmniRoute/issues/6662)) — every chunk builder in both adapters hardcoded `delta: { content: ... }` with no reasoning path, unlike the established pattern already used by `default.ts`/`deepseek-web.ts`/`bedrock.ts` and the real-Anthropic-API `claude-to-openai.ts` translator (`thinking_delta` → `reasoning_content`). `v0-vercel-web.ts` now forwards an upstream `delta.reasoning_content` field (streaming and non-streaming) the same way `deepseek-web.ts` does. `claude-web.ts`'s `buildClaudeStreamingResponse` now maps a `content_block_start`(`type: "thinking"`)/`content_block_delta`(`delta.thinking`) pair onto `delta.reasoning_content`, and `claude-web/payload.ts`'s `transformToClaude()` no longer hardcodes `thinking_mode: "off"` — a new `wantsExtendedThinking()` derives it from the request's `reasoning_effort`/`reasoning.effort`/`thinking.type` signal, so extended thinking can actually be requested. Regression guard: `tests/unit/issue-6662-repro.test.ts` (RED→GREEN for both adapters). ([#6743](https://github.com/diegosouzapw/OmniRoute/pull/6743)) +- **fix(api):** the compression config PUT schema now accepts `enableRenderers` for the RTK engine instead of rejecting the documented option (#6703, #6757 — thanks @alltomatos, with an independent duplicate fix from @chirag127 via #6756). +- **fix(api):** raised the provider `apiKey` length cap for cookie-based web providers, whose session-cookie credentials legitimately exceed the previous limit (#6715, #6759 — thanks @alltomatos). +- **fix(routing):** fusion combos no longer silently drop `combo-ref` panel members — a referenced combo is now dispatched as one black-box panel voice instead of being dropped (#6764) +- fix(ci): publish electron-updater `latest*.yml` manifests in electron release assets so auto-update can find them ([#6766](https://github.com/diegosouzapw/OmniRoute/issues/6766)) +- **fix(i18n): translate hardcoded Portuguese dashboard strings to English (#6761, #6768)** (#6769 — thanks @chirag127). +- fix(providers): strip redundant node prefix when resolving custom OpenAI/Anthropic-compatible connections by raw connection id, preventing double-namespaced model ids from 400ing upstream (#6772) +- fix(providers): scope nvidia NIM 404s to the single failing model instead of cooling down the whole connection (#6773) +- **fix(codex):** bump the default Codex CLI client identity from `0.142.0` to `0.144.0` for compatibility with newer Codex-backed models ([#6780](https://github.com/diegosouzapw/OmniRoute/pull/6780)) — thanks @quanturbo +- **fix(ci):** the blocking "Impacted unit tests (TIA)" step false-redded any PR whose impact graph reached a dashboard component — it ran every selected test under `--import tsx/esm`, but `tests/unit/dashboard/**` requires the `--import tsx` CJS transform (ESM-only deep imports like `@lobehub/icons/es/*`), exactly as the canonical `test:unit:ci:shard` already does per segment. The impacted selection is now split by segment with matching loaders (closes #6787). ([#6788](https://github.com/diegosouzapw/OmniRoute/pull/6788)) +- **fix(translator):** read PDF/video `file_data` attachments on the OpenAI→Gemini/Antigravity and OpenAI→Claude paths so multimodal documents (not just images) reach the upstream — PDFs map to `document`/`inlineData` and videos keep their `video/mp4` mime instead of being dropped (#6790 — thanks @Witroch4, with an independent report/fix from @samimozcan via #6762/#6753). +- **fix(providers): ensure DeepSeek Web SSE emits [DONE] after FINISHED** (#6791 — thanks @Pitchfork-and-Torch). +- **fix(api):** the compression config `PUT` schema (`stackedPipelineStepSchema`) now accepts every `ENGINE_CATALOG` id — the structural engines `session-dedup`/`ccr`/`headroom`/`relevance`/`llmlingua`/`omniglyph` and the `aggressive` `ultra` intensity — so a `GET`→`PUT` round-trip of a stacked pipeline no longer 400s on a valid engine the discriminated union had omitted (#6747 — thanks @Pitchfork-and-Torch). +- **fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594)** (#6794 — thanks @huohua-dev). +- **fix(cursor):** send the Agent CLI build id as `x-cursor-client-version` so Cursor upstream accepts requests from the current CLI build instead of a stale hardcoded version (#6795 — thanks @andrewmunsell). +- fix(cli): waitForServer() no longer reports ready from a raw TCP accept alone — requires a fast HTTP rejection or a real health response, so the "OmniRoute is running!" banner no longer fires 30-60s before the server can actually answer requests (#6800) +- fix(sse): de-flake timing-sensitive combo cooldown/breaker tests + add explicit MCP audit shutdown timeout (#6803) +- **fix(codex): strip include from compact responses requests** (#6805 — thanks @yinaoxiong). +- fix(dashboard): surface Claude extraUsage credits in quota card when quotas is empty (#6806) +- **Request count by provider & date**: Dashboard → Analytics now shows a dedicated table of request counts grouped by provider and calendar date (plus token totals), for providers that bill per-request rather than per-token — sortable columns and a single-date filter. New `getProviderDailyUsageRows()` query (`src/lib/db/usageAnalytics.ts`) and its own `GET /api/usage/requests-by-provider-date` route (kept separate from the frozen `/api/usage/analytics` route). Regression guard: `tests/unit/db-provider-daily-usage-4009.test.ts`. (#4009 — thanks @tjengbudi) ([#6812](https://github.com/diegosouzapw/OmniRoute/pull/6812)) +- **fix(resilience):** an Ollama Cloud (or any apikey-category provider) account that hit a weekly usage cap kept getting retried every few minutes instead of backing off ([#3709](https://github.com/diegosouzapw/OmniRoute/issues/3709)) — the upstream 429 body ("you (\) have reached your weekly usage limit") was invisible to `checkFallbackError`'s existing subscription-quota-text classifier (Issue #2321) because that branch is gated by `shouldUseQuotaSignal`, which is oauth-only, so apikey providers like `ollama-cloud` fell through to the generic exponential backoff (~1s, capped at 2min) — one account took 285x429 in 48h. A new `isWeeklyUsageLimitText`/`buildWeeklyQuotaFallback` classifier (extracted, with the existing subscription-quota logic, into a new `open-sse/services/quotaTextCooldowns.ts` module so the frozen `accountFallback.ts` didn't have to grow) runs unconditionally and applies a 24h `QUOTA_EXHAUSTED` cooldown regardless of provider category. Regression guard: `tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts`. ([#6817](https://github.com/diegosouzapw/OmniRoute/pull/6817)) +- **fix(providers):** an explicit `thinking.budget_tokens: 0` is now honored in the OpenAI→Gemini transform (thinking disabled) instead of being treated as unset (#6813, #6821 — thanks @alltomatos). +- **fix(bootstrap):** filter empty `process.env` values before spawning embedded services so a blank env var no longer crashes the Docker bootstrap in a restart loop (#6828 — thanks @AndrianBalanescu). +- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu). +- **fix(db):** cap the sql.js OOM-during-probe path in `getDbInstance()` at 3 attempts with a terminal diagnostic — previously only the generic-corruption probe-failure path had a cycle-breaker (#6632), so a persistently OOMing `storage.sqlite` probe re-threw the identical error forever on every call from every background poller, hanging the app with "Internal Server Error" and no self-recovery (#6835). +- fix(mcp): de-duplicate `TOTAL_MCP_TOOL_COUNT` by tool name instead of double-counting collections (#6854) +- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari) +- **fix(plugin):** the `@omniroute/opencode-plugin` dynamic provider hook stopped embedding its OC-1.17.8+-gate-compatible `opencode-`-prefixed provider id into model routing fields (`ModelV2.id`/`providerID`, combo catalog keys) — OmniRoute's server has no `opencode-` provider alias, so every dispatched model failed credential lookup with "No credentials for opencode-omniroute" (#6859). +- fix(sse): apply cliproxyapiModelMapping at CLIProxyAPI dispatch time (#6876) +- fix(sse): defer `response.completed` until a trailing usage-only chunk arrives on `/v1/responses` streams (#6906) +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) +- fix(sse): wire the shared quota-fetch throttle into DeepSeek, Bailian, OpenCode, and Crof quota fetchers, not just Codex (#6911) +- fix(sse): rename client-sent `max_completion_tokens` to `max_tokens` for providers/models that only accept the legacy field (e.g. Volcengine Ark / DeepSeek), mirroring the existing reverse rename from #1961 (#6912) +- fix(providers): `PROVIDER_LIMITS_SYNC_SPACING_MS` now also throttles local / API-key (Ollama) connections, not just OAuth — spaced between concurrency chunks so a local endpoint isn't hit by a simultaneous refresh burst (#6916) +- fix(sse): classify LAN embeddings providers (10/8, 192.168/16, CGNAT) as no-auth instead of forcing bearer auth (#6925) +- fix(sse): Qwen Web executor no longer sends `[object Object]` when a message uses structured (array) content — the text parts are now flattened (#6927) +- perf(api): relay chat-completions routes now thread the already-fetched `RelayToken` into `checkRateLimit`, skipping a redundant `SELECT * FROM relay_tokens WHERE id = ?` re-query on every request (#6930) +- fix(sse): `normalizeCodexMessageContentPart` now rewrites explicit `type: "input_text"` (not just `type: "text"`) to `output_text` on assistant-role Codex Responses input parts, so replayed assistant history sent by codex-cli as `input_text` is no longer rejected by the Codex/OpenAI backend (#6932) +- fix(sse): omit removed `attachments` field from Muse Spark Web (Meta AI) persisted GraphQL query to fix `Unknown type "AttachmentInput"` 502s (#6935) +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) +- fix(api): model-list discovery for LAN-local OpenAI-compatible providers (e.g. LM Studio) now uses the same local-first SSRF guard as the connection test, instead of the stricter guard that always blocked LAN hosts (#6939) +- fix(providers): `openai->gemini` transform now maps `reasoning_effort: "none"` to `thinkingConfig.thinkingBudget: 0` (with `includeThoughts: false`), giving callers an explicit, documented off-switch for Gemini thinking; the no-knob-at-all default injection (#4170) is unchanged (#6813, thanks @rafaumeu) +- **fix(sse):** escape backslash before brackets in ChatGPT-web citation link text, preventing a citation label containing `\` from corrupting the generated Markdown link ([#6944](https://github.com/diegosouzapw/OmniRoute/pull/6944)) — thanks @brick30llc-ctrl +- fix(oauth): tokenHealthCheck now lowercase-normalizes `conn.provider` before checking `ROTATING_REFRESH_PROVIDERS.has()` and the GitHub Copilot sub-token refresh guard, so mixed-case provider values (e.g. "OpenAI", "Github") no longer bypass the rotating-refresh-token skip or the Copilot sub-token refresh (#6947) +- fix(sse): make Codex Responses tool-arg normalization schema-aware — drop values equal to the tool's declared JSON Schema `default`, generalize empty-optional stripping to any tool (not just `Read`/`Subagent`) via `schema.required`, and thread each tool's schema from the request's `tools[]` into the streaming response translator (#6951) +- fix(sse): drop internal commentary-phase Responses output in TRANSLATE-mode streams, not just PASSTHROUGH — codex/Responses-upstream routes translated into another client format (e.g. Claude Code) no longer leak duplicate prose and narrated tool-call arguments into the client text channel (#6952) +- fix(sse): stop forwarding empty-signature thinking blocks verbatim to Anthropic-native legs, which permanently poisoned combo fallback (#6953) +- **fix(sse):** `perplexity-web`'s default `pplx-auto`/`pplx-sonar` targets now post `mode: "copilot"` (with `pplx-sonar` mapped to `model_preference: "turbo"` instead of `experimental`), match Perplexity's `event: end_of_stream` SSE terminator instead of OpenAI's `[DONE]`, and fall back to the COMPLETED frame's double-encoded FINAL step-blob when no `diff_block`/`markdown_block` streamed — fixing `[perplexity-web/pplx-sonar] Provider returned empty content` against the current schematized `www.perplexity.ai` SSE API. (thanks @artickc) +- **fix(combos):** embeddings-only and rerank-only models (e.g. JinaAI, Gemini auto-imported, OpenRouter custom, reranker models) no longer disappear from the combo builder's model picker — the leftover chat-only `isChatCapable` gate in `addModelOption()` has been removed (#6975). +- **fix(combos):** when 2+ distinct model ids from the same provider would render an identical display name in the combo builder picker (e.g. Mistral's `codestral-latest`/`codestral-2508` aliases sharing one upstream catalog name), each colliding entry now falls back to its own id as the display label so every row stays visually distinguishable and findable (#6957). +- **fix(dashboard):** the combos builder now hides provider connections the user has explicitly disabled, instead of relying only on stale test-status (#6984 — thanks @attid). +- **fix(providers):** cap grok-cli tools at 200 per request, matching xAI's cli-chat-proxy limit, and document the non-reasoning capability of grok-build/grok-composer-2.5-fast in the registry (#6986, thanks @gitcommit90) +- fix(providers): DuckDuckGo AI Chat executor propagates the real upstream status (429 rate limit with `Retry-After`) instead of misclassifying VQD-token acquisition failures as a hardcoded 503 (#6996) +- fix(providers): refresh OpenCode (`oc`) free-tier model catalog — 6 delisted IDs replaced with the 4 currently-live free models (#6998) +- fix(api): raise the main server's `keepAliveTimeout`/`headersTimeout` well above Node's 5s default so pooled keep-alive clients (e.g. JetBrains AI Assistant's JVM `HttpClient`) stop getting 0 bytes back on a reused connection (#7003) +- fix(compression): wire the adaptive context-budget "dial" (`contextBudget`) into the settings schema and DB so it can actually be persisted via `PUT /api/settings/compression`, instead of being silently rejected (#7005) +- fix(usage): stop opencode-go quota lookup from defaulting to an unrelated Z.AI endpoint (#7022) +- **fix(providers):** Auggie (Augment CLI) model registry updated to the real v0.32.0 CLI model IDs, with a live `auggie model list` auto-discovery fallback for future renames; the old pre-v0.32.0 IDs (`claude-sonnet-4.6`, `claude-opus-4.6`, `claude-haiku-4.5`, `gemini-3.1-pro`, `gemini-3.0-flash`, the `gpt-5.4`/`gpt-5.5` high/medium variants) are a **breaking rename**, but a backward-compat alias map in `resolveAuggieModel()` transparently remaps them to their v0.32.0 equivalents so existing saved combos keep working without any manual update (#7032 — thanks @oyi77). +- fix(ci): add a dashboard-scoped typecheck gate covering `src/app/(dashboard)` TSX, previously invisible to `typecheck:core` and `next build` (#7033) +- **fix(cli):** `omniroute dashboard` (no `--port` flag) now respects `PORT` from the environment instead of always opening `localhost:20128`, matching `serve`/`launch` precedence (`--port` > `PORT` env > `20128` default) (#7049 — thanks @kaon0388v1). +- fix(build): extend the Turbopack `ignoreIssue` suppression to `open-sse/services/compression/**`, matching the `getModuleDir()` dynamic-path fs pattern already suppressed for `src/lib/agentSkills/**` in #6582, eliminating the remaining 610 "Overly broad patterns" warnings (#7051) +- fix(providers): web-cookie connection-test/cookie-validation probe (zai-web and every other registry-entry web-cookie provider) now honors the configured HTTP/SOCKS proxy — the `/models` probe routed through `directHttpsRequest`'s hardcoded native-fetch bypass, silently skipping proxy resolution even though the executor's actual chat traffic already respected it (#7058) +- fix(resilience): recognize Ollama Cloud's 5-hour session usage-limit 429 as quota-exhausted instead of a generic rate limit (#7071) +- fix(dashboard): restore mobile single-column fallback on the Provider Quota page card grid, fixing clipped labels/buttons on phone-width viewports (#7072) +- fix(dashboard): include proxyId when testing a saved registry proxy so SOCKS5/auth credentials are loaded (#7080) +- **fix(sse):** xiaomi-tokenplan `mimo` models (e.g. `mimo-v2.5-pro`) are now recognized as thinking-mode upstreams that require `reasoning_content` echoed back on every assistant turn, fixing a persistent `400 reasoning_content must be passed back` error on multi-turn conversations ([#7098](https://github.com/diegosouzapw/OmniRoute/pull/7098)) — thanks @xxue-z +- **fix(dashboard):** align onboarding tier descriptions and localize the tier step header and flow copy ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- **fix(sse):** claude-web now surfaces the real upstream error body for non-SSE 400/403/429/500 responses instead of reporting "no response body" — the streaming client was discarding the already-captured temp-file bytes and reading the native binding's empty in-memory body field instead (#7134). +- fix(db): honor combo-level proxy assignments from the registry when resolving a connection's proxy (#7149) +- fix(dashboard): wire modelAliases fetch into HermesAgentToolCard so OpenRouter and other passthrough providers appear in the Hermes Agent role picker (#7151) +- fix(dashboard): filter hidden custom models out of the legacy combo model picker (#7156) +- fix(dashboard): Agent Bridge DNS toggle now sends POST (was PUT), fixing HTTP 405 on Start/Stop DNS (#7157) +- fix(dashboard): implement missing `handleToggleSource` callback on the Free Pool tab so the page no longer crashes with a `ReferenceError` (#7161) +- fix(sse): stop duplicating text in Gemini Web streamed responses (#7163) +- **fix(executors):** Codex Responses Lite requests force serial tool calls required by the upstream API ([#7171](https://github.com/diegosouzapw/OmniRoute/pull/7171)) — thanks @fenix007 +- **fix(translator):** preserve Gemini thinking-mode `thought:true` parts as `reasoning_content` instead of leaking them into visible assistant text on the OpenAI request bridge. (thanks @warelik) +- **fix(translator):** register the missing OpenAI→Gemini response projection so combo-routed OpenAI-native providers no longer leak raw `chat.completion.chunk` shapes to Gemini-format clients. (thanks @warelik) +- **fix(cli):** `omniroute --version` now fast-paths before the tsx/esm + polyfill imports, env-file loading, and Commander's full command registration, cutting local runtime from ~1.5s to ~0.3s. (thanks @Jordannst) +- fix(ci): build dast-smoke and nightly API-only smoke workflows with `OMNIROUTE_BUILD_BACKEND_ONLY=1` to skip the unused dashboard UI graph and stop the multi-minute build variance/timeouts (#7226) +- **api:** bulk-add API keys no longer overwrite existing provider connections — a colliding auto- or custom-generated name now gap-fills a free suffix instead of silently replacing a saved connection's key/state. (thanks @asynx6) +- fix(sse): feed the compression pipeline the authoritative vision capability instead of the conservative model-id heuristic, so vision models absent from the fragment list (e.g. gpt-5.5) no longer have their image_url blocks silently stripped (#7237) +- **fix(sse):** route the public OpenAI GPT-5.6 family (`gpt-5.6`, `-sol`, `-terra`, `-luna`) through the Responses API — Chat Completions rejects GPT-5.6 requests that combine function tools with an active `reasoning_effort`. (thanks @Jordannst) +- **fix(providers):** honor a configured proxy on Grok Build egress — the grok-cli executor used raw `https.request()` and bypassed the proxy context, leaking the host IP on chat inference and OAuth token refresh. (thanks @ryanngit) +- **fix(nvidia):** expand NIM chat model catalog with newly-observed models. (thanks @spacesky-cell) +- **fix(sse):** synthetic bypass responses for Claude-format clients no longer drop their content — `mergeChunksToResponse()` now reconstructs the message from streamed content blocks instead of returning an empty array. (thanks @KunN-21) +- **fix(build):** isolate Windows HOME/AppData during next build. (thanks @KunN-21) +- fix(dashboard): providers model-name filter now matches an aggregator's live/synced catalog, not just the static curated registry (#7250) +- fix(docs): correct stale `/api/version` and migration-125 references + realign `no-explicit-any` suppression counts drifted by base-red realignment commits (#7253) +- fix(sse): project non-streaming JSON responses back to the Gemini/Antigravity `{response:{candidates}}` envelope instead of leaking the raw OpenAI `choices[]` shape, so tool calls are no longer dropped for Gemini-family clients on the JSON path (#7255) (thanks @warelik) +- fix(i18n): treat `__MISSING__:` sync-script placeholders as absent so the EN fallback renders instead of the raw sentinel (#7258) +- fix(authz): classify /api/cli-tools/forge-settings and /api/cli-tools/jcode-settings as LOCAL_ONLY, closing an RCE-via-tunnel gap where getCliRuntimeStatus() spawns a child process without loopback enforcement (#7263) +- fix(sse): lazy-load playwright in claudeTurnstileSolver so unsupported platforms (e.g. Termux/Android) don't crash on boot (#7265) +- **fix(sse):** stop logging a caller-initiated request abort/timeout as a noisy proxy transport failure in `proxyFetch`. (thanks @TuyulSpam) +- fix(sse): classify 401 "model X is not supported" as model-not-found so it locks the model out instead of looping forever (#7268) +- fix(dashboard): resolve `ReferenceError: t is not defined` crashing `/dashboard/costs` when a filtered slice has zero-cost rows (#7272) +- fix(cli): Windows MITM root-CA check/uninstall keyed off the hardcoded legacy hostname `daily-cloudcode-pa.googleapis.com` instead of the actual generated CA's identity — they now derive a SHA-1 thumbprint from the real `certPath` file (same pattern `#6338` used for the DNS side of this anti-pattern) (#7275) +- fix(cli): reuse cliRuntime's win32-aware `locateCommand`/`shell:true` probe in tool-detector so installed CLIs (npm `.cmd` shims) are no longer reported as absent on native Windows (#7279) +- fix(dashboard): connection Test surfaces a rate-limit warning on 429 chat-probe responses instead of an unqualified pass (#7284) +- fix(sse): combo failover now detects OpenAI-shape streams truncated without `finish_reason`/`[DONE]` (#7285) +- **fix(db):** `getDbInstance()` now guarantees sql.js WASM has already been pre-initialized (via a top-level await in `src/lib/db/core.ts`) before ANY consumer can reach it, closing an ordering gap where early startup steps (`ensureSecrets()`, `clearStaleCrashCooldowns()`, `getSettings()`, `initAuditLog()`) called `getDbInstance()` before `ensureDbReadyForBoot()` had a chance to run `preInitSqlJs()` — turning a recoverable driver failure into a hard boot crash (`sql.js WASM ainda não foi pré-inicializado`) whenever both `better-sqlite3` and `node:sqlite` failed to open an existing `storage.sqlite`. `tryOpenSync()` also now logs the real underlying cause of each swallowed sync-driver failure instead of an empty `catch {}`. (#7288, #7494) +- fix(sse): split effort/reasoning suffix off pinned Claude/GPT model ids before sending to cursor's server (#7289) +- fix(sse): hoist client-injected `system` messages to index 0 for strict OpenAI-compatible providers (xiaomi-mimo) regardless of origin (#7293) +- fix(sse): treat Uint8Array/Buffer as opaque binary in log redaction to stop per-byte enumeration on Bedrock Converse image requests (#7297) +- fix(cli): load DATA_DIR/server.env as a fallback for .env when migrating from Electron, so STORAGE_ENCRYPTION_KEY/JWT_SECRET/API_KEY_SECRET survive an Electron→CLI install migration (#7302) +- **fix(rerank):** Honor the connection's pinned proxy on rerank calls, so a provider that geo-blocks the host IP (Voyage AI) works on the same connection where chat and embeddings already did ([#7350](https://github.com/diegosouzapw/OmniRoute/issues/7350)) — thanks @kamenkadmitry +- **fix(electron):** Normalize hashed Turbopack external imports in packaged desktop builds, preventing instrumentation startup failures ([#7353](https://github.com/diegosouzapw/OmniRoute/pull/7353)) — thanks @tianrking +- fix(chatgpt-web): recognize `update_content.messages[]` (plural array) celsius WebSocket frames so async image_gen pointers are no longer silently dropped (#7357) +- fix(sse): clamp glm-4.6v max_tokens to the 32768 ceiling for zai and glm providers, wiring stripUnsupportedParams into GlmExecutor's own transform path (#7364) +- fix(sse): honor per-model targetFormat override for zai/glm-coding-apikey buildUrl and make custom-model id lookup case-insensitive (#7364) +- fix(sse): combo session stickiness now releases a connection whose per-window quota is exhausted, matching the provider-level session-affinity pin (#7387) +- fix(cli): log Codex Responses WebSocket history/usage per logical turn instead of once per connection (#7388) +- fix(embeddings): remove the non-existent `voyage-multilingual-3.5` from the embedding registry and add the missing Voyage models (#7425 — thanks @kamenkadmitry) +- fix(providers): expose a base-URL override for Kimi/Moonshot so CN-region API keys (issued on platform.kimi.com / moonshot.cn) can be pointed at api.moonshot.cn instead of being rejected by the international host (#7447) +- fix(build): align `engines.node` supported range (>=22.22.2 <23 || >=24.0.0 <27) across package.json, lockfile, README engine references and the node-runtime support test, so install-time engine checks match the actually-tested runtimes (#7446) +- fix(i18n): replace machine-bulk-filled Vietnamese UI strings with human-quality translations — 5411 values improved, technical literals (RPC methods, endpoints) no longer over-translated (#7493) +- fix(db): stop closing the single sql.js singleton during getDbInstance()'s probe/reopen sequence, which poisoned every boot with "Database closed" once both sync SQLite drivers were unavailable (#7494) +- fix(sse): stop stream readiness from treating a choices-less mid-stream error frame as a successful stream, so combo can fail over instead of returning zero `choices` (#7503) +- Fixed the Codex connection **Test** button always reporting success for ChatGPT-account tokens: the probe used `gpt-5.3-codex`, a codex-only model ChatGPT accounts reject with a 400 — the same status the probe treats as "auth OK", so a bad token was indistinguishable from a good one. It now probes with `gpt-5.5`, a model ChatGPT-account sessions actually support (#7521). +- The Codex account import (`POST /api/oauth/codex/import`) now validates each record's `refresh_token` against OpenAI's OAuth endpoint before persisting the connection: an already-invalidated session (`refresh_token_invalidated` / a dead `auth.json`) is rejected with a clear "run `codex login` again and re-import" message instead of importing as `active` and failing confusingly on first use. Valid tokens import as before, with any rotated tokens applied (#7522). +- The PKCE OAuth start (`/api/oauth/[provider]/start-callback-server`, used by Codex/Windsurf/Devin) now detects when OmniRoute is being driven from a remote host and returns a reverse-tunnel hint (`remoteHost`, `tunnelCommand`, `message`) instead of hanging silently: the callback server binds the *server's* localhost:PORT, so a browser on a different machine would redirect to its own localhost and never complete. Loopback access is unchanged (#7523). +- fix(providers): search providers now expose a static model catalog derived from `searchTypes`, fixing "does not support models listing" 400 for serper-search, brave-search, perplexity-search, exa-search, tavily-search, google-pse-search, youcom-search, searxng-search, zai-search (#7529) +- fix(sse): map `tool_search` to a Chat function tool instead of dropping it during Responses->Chat translation (#7532) +- fix(sse): gate `verbosity`/`prompt_cache_key` on OpenAI destination during Responses->Chat translation, stopping the leak to non-OpenAI upstreams like NVIDIA (#7533) +- fix(api): Usage page "by provider" table now shows the configured provider display name (e.g. "OpenAI Codex") instead of the raw internal provider id (e.g. "codex") (#7534) +- fix(api): Usage page "model usage" table no longer lists the same logical model twice when it was recorded under both a bare and a provider-prefixed spelling (e.g. `glm-5.2` and `z-ai/glm-5.2`) — the in-memory dedup key now uses the normalized model name (#7535) +- fix(codex): non-stream Codex (ChatGPT-account) chat no longer 502s with "Response body is already used". `peekCodexSseTransientError` now checks the content-type before touching `response.body`: on the wreq-js TLS-fingerprint transport the Response is backed by a native body handle and merely accessing `.body` disturbs it, so the empty-content-type non-stream response was being consumed by the peek guard and then re-read by `readNonStreamingResponseBody`. Streaming was unaffected. Validated live on the VPS (`codex/gpt-5.5` + `codex/gpt-5.6-terra` non-stream now return 200) (#7536) +- **fix(sse):** preserve `input_image` parts in array-valued Codex `custom_tool_call_output` payloads instead of rewriting them to invalid `output_text` parts ([#7540](https://github.com/diegosouzapw/OmniRoute/pull/7540)) - thanks @loulanyue +- fix(providers): stop reporting Arena (lmarena) cookie validation as Invalid when the `/models` probe hits a 307 redirect — degrade to `unsupported` instead, and drop the stale "no registry entry" comment for lmarena (#7542) +- **fix(combo):** streaming combo failover now fails over when an upstream SSE response is truncated mid-lifecycle with no recognised terminator (`data: [DONE]`, `finish_reason`, `message_stop`/`message_delta` with `stop_reason`, or a terminal `usage`-only chunk) and no structured SSE frame at all — previously any byte, even unparseable garbage, satisfied the generic done-branch gate and the truncated stream was passed through, leaving the client hung waiting for events that never arrived ([#7545](https://github.com/diegosouzapw/OmniRoute/pull/7545)) — thanks @Chewji9875 +- **fix(dashboard):** Public and managed tunnel endpoints now take precedence over loopback URLs in dashboard setup and copyable API configuration ([#7547](https://github.com/diegosouzapw/OmniRoute/pull/7547)) — thanks @nguyenha935 +- fix(claude-web): unify Turnstile solver, executor and httpBackedChat fast-path User-Agents behind one shared fingerprint module so `cf_clearance` is never solved under a different UA than the one that replays it (#7548) +- fix(cli): fall back to the node:sqlite driver cascade in `bin/cli/sqlite.mjs` so `omniroute doctor` no longer reports a false "FAIL Database"/"FAIL Storage/encryption" on machines without a working better-sqlite3 native binary (#7586) +- fix(api): expose Responses-API-format (OpenAI/Codex) chat models on every VS Code Ollama-compatible listing route, not just `/models` (#7587) +- **grok-cli:** OAuth paste-import now requires the full `~/.grok/auth.json` (with `refresh_token`) instead of a bare JWT `key`, preventing connections that can never auto-refresh (#7610). +- fix(sse): proactively refresh Grok Build's expiring OAuth token before dispatch, and add it to the connection-test config so "Test Connection" no longer reports "unsupported" (#7610) +- **grok-cli:** sanitize Responses `function_call_output.output` values before dispatch so incomplete `\u` escapes / malformed tool results no longer cause intermittent 400 body-parse failures on cli-chat-proxy (#7611). +- **fix(translator):** guard against double-emission when `response.completed` echoes `function_call` items already streamed via incremental `output_item.added`/`done` events — skip synthesis for `call_id`s already tracked, preventing duplicate tool call chunks for incrementally-streaming providers +- fix(routing): strip `prompt_cache_key` for NVIDIA NIM — Codex CLI injects it, NIM's OpenAI-compatible wrapper 400s on it (#7617) +- fix(routing): honor eye-icon hidden models for no-auth providers in auto-combo candidate pools (#7620) +- fix(providers): correct Chutes registry baseUrl from api.chutesai.com to llm.chutes.ai (#7621) +- fix(providers): unify connection status across dashboard surfaces, deduplicate provider cards, preserve no-auth model discovery for metadata-only rows, and route playground models through the provider alias (#7629) +- fix(providers): classify Mistral ambiguous 401 (quota vs revoked key) instead of asserting hard auth failure (#7638) +- fix(sse): route CLIProxyAPI fallback/passthrough legs through a dedicated `cliproxyapi_api_key` credential instead of the failed native provider's own key (#7645) +- fix(packaging): move fumadocs-mdx from dependencies to devDependencies to avoid pulling its build-only yuku-analyzer/yuku-ast toolchain into `npm install -g omniroute` (#7661) +- GET /api/combos/auto now enumerates template variants (auto/best-coding, auto/pro-_, auto/claude-_, auto/best-free) and family variants (auto/glm, auto/llama, auto/gemini, etc.) in addition to the flat and suffix variants it already exposed. Previously these 27 variants were advertised by /v1/models but missing from the combos endpoint, causing 404s when clients tried to use them. +- fix(sse): persist rotated Gemini web-session cookies via onCredentialsRefreshed (#7676) +- fix(dashboard): mirror connection-row action-icon spacing under RTL via Tailwind logical utility (#7680) +- fix(cli): split `outboundUrlGuard.ts`'s DB/feature-flag helpers into `outboundUrlGuardPolicy.ts` so `omniroute setup-opencode` no longer crashes with `Cannot find package '@/shared'` on a global npm install (#7682) +- fix(sse): wire settings.wildcardAliases into model resolution so wildcard model aliases created in Settings actually take effect (#7693) +- fix(mcp): copy undici into dist/node_modules to prevent hollow-package shadowing crash (#7701) +- **fix(translator):** sanitize `tool_result.tool_use_id` symmetrically with the assistant's `tool_use.id` in the OpenAI→Claude request translator — a raw tool-call id containing characters outside `[a-zA-Z0-9_-]` (e.g. dots, colons) previously diverged from its sanitized `tool_use.id` counterpart, causing `enforceToolResultAdjacency()` to silently drop the `tool_result` and Anthropic to reject the request with HTTP 400 (#7705) +- **fix(db):** bulk proxy imports now update an existing proxy when only its password changes instead of creating a duplicate ([#7707](https://github.com/diegosouzapw/OmniRoute/pull/7707)) — thanks @floze-the-genius +- fix(oauth): stop Codex OAuth completion from collapsing distinct accounts that share an email but have no workspaceId, by requiring chatgptUserId agreement before merging (#7737) +- fix(db): purge in-memory API-key health/rotation state when a provider connection is deleted (#7740) +- **perf(db):** the 5 provider-connection/node call sites [#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787)'s IC2 conversion missed — `providers/[id]/models`, `v1/provider-plugin-manifest`, `localHealthCheck.ts`, `sync/bundle.ts` — now read through `getCachedProviderConnectionById`/`getCachedProviderNodes`; `tokenHealthCheck.ts` keeps uncached `getProviderConnectionById` reads at the unrecoverable-refresh-error and GitHub Copilot sub-token-refresh call sites to avoid a CAS-staleness regression. ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744) — thanks @oyi77) +- fix(compression): CCR no longer collapses a whole prompt into a bare, unretrievable `[CCR retrieve hash=...]` marker on non-MCP upstreams — a short preamble of the original text is always kept alongside the marker (#7746) +- fix(sse): strip orphaned tool_use blocks before dispatching to Antigravity/Vertex Claude models, mirroring the mainline Claude executor's #2382 guard (#7752) +- fix(cli): resolve Windows CLI detection false negatives — nvm-windows symlinked binaries no longer rejected as symlink_escape, and a stray known-path artifact no longer hides a genuinely runnable Claude CLI on the PATH fallback (#7753, #7774) +- fix(dashboard): keep session/weekly quota rows in a stable fixed order on collapsed provider-quota cards, matching the already-fixed expanded view (#7764) +- fix(db): log the fatal boot-time SQLite driver-cascade failure before it propagates instead of swallowing it silently, so `app.log` captures the real cause on Termux/Android (#7773) +- **fix(sse):** Claude-Code-compatible bridge (AgentRouter and any CC provider) no longer loses vision input from OpenAI-format clients (OpenCode/Kilo/Cline): `image_url`, AI-SDK `image` and Chat Completions `file` parts are now converted to Claude `image`/`document` blocks before dispatch, and media-only user turns are no longer dropped by the empty-content filter. (thanks @beingshafin) ([#7777](https://github.com/diegosouzapw/OmniRoute/issues/7777)) +- **perf(db):** `getProviderConnections` now reads from a shared `rawConnectionsCache` (500-entry LRU, 5s TTL) and returns lazy-decrypting proxies — encrypted credential fields (`apiKey`, `accessToken`, `refreshToken`, `idToken`) are only AES-GCM decrypted on first property access instead of eagerly for every cached row. `getCachedProviderConnections` now delegates through this single raw cache instead of maintaining its own, and `deleteProviderConnectionsByProvider` gained a missing `invalidateDbCache` call. ([#7787](https://github.com/diegosouzapw/OmniRoute/pull/7787) — thanks @oyi77) +- fix(docs): document CREDENTIAL_REDACTION_ENABLED and GHE_COPILOT_OAUTH_CLIENT_ID in .env.example/ENVIRONMENT.md, closing the env-doc-sync gate drift (#7793) +- fix(combo): retry intermediate pipeline-strategy steps on transient upstream errors (429/502/503/504), gated by `combo.config.maxRetries`/`retryDelayMs`, without retrying terminal auth/request errors (#7794 — thanks @AndrianBalanescu) +- fix(docker): repair tls-client-node native binary after --ignore-scripts, retry rate-limited GitHub fetches (#7802) +- **fix(runtime):** Apply refreshed request-queue settings, restore inter-batch health-check jitter, and invalidate database read caches when the SQLite singleton resets; refresh stale CI baselines and fixtures exposed by clean release runs ([#7812](https://github.com/diegosouzapw/OmniRoute/pull/7812) by [@backryun](https://github.com/backryun)). +- fix(oauth): attempt Antigravity onboarding inline when `projectId` is empty, fixing a regression from #5193 that re-introduced the #2541 catch-22 for new accounts (#7814) +- fix(api): add amazon-q to the static model catalog so "Available Models" no longer 400s (#7820) +- fix(sse): preserve parallel_tool_calls for GPT-5.6 ultra/max delegation under Codex Responses Lite (#7821) +- fix(quality): tolerate ESLint's trailing unpruned-suppressions stderr text in validate-release-green (#7837) +- fix(test): widen ratelimit-admission pollUntil deadline to 10s to end nightly-compat flake (#7842) +- **fix(cli):** Windows `omniroute dashboard` browser fallback uses `rundll32` instead of `cmd.exe` to open the dashboard URL, avoiding an unnecessary shell spawn ([#7844](https://github.com/diegosouzapw/OmniRoute/pull/7842)) +- fix(dashboard): Request Logs detail modal no longer crashes when the persisted error is a structured object (#7845) +- fix(backend): stop `buildClientRawRequest` deep-cloning the whole request body on every chat request (#7847) — every consumer of `clientRawRequest.body` is observability and keeps at most a bounded copy, so the unbounded clone retained ~41x more than anything used it (3.19 MiB vs 0.08 MiB on a 3.05 MiB / 729-message agent request). Also makes `cloneBoundedForLog` idempotent: arrays, objects and strings all exceeded their own bounds once the truncation marker was added, so re-bounding an already bounded payload silently dropped a further item and misreported the original length +- fix(sse): copy the combo attempt body shallowly instead of deep-cloning it per target (#7847) — the deep clone cost 9.53 MiB at 3 targets and scaled linearly with the target count (31.78 MiB at 10) on a 3.05 MiB agent request, while the isolation it provided only ever needed to contain top-level scalar writes. Also fixes a real cross-target leak in round-robin, which copied the body only when the reasoning buffer changed `max_tokens` and otherwise shared the caller's object, so a Background Task Redirection on one target rewrote `body.model` for the next +- fix(sse): estimate the combo fallback-compression trigger from the request object instead of `JSON.stringify(...)` (#7847) — the string path charged an inline base64 image as if every character were prose (~50k tokens instead of ~1.2k on a 200 KB image), falsely tripping compression on requests nowhere near the context window; the same over-count #8368/#8401 fixed elsewhere. Adds `jsonLength()`, an exact serialized-length walker (property-tested against `JSON.stringify`), and uses it for the readiness-timeout and token estimates so a multi-megabyte body is no longer materialized as a string just to be measured +- fix(providers): Copilot reasoning_text now surfaces in Claude-format non-stream responses, fixing spurious 502s (#7856) +- fix(providers): treat a non-401/403 response from the web-cookie `/models` validation probe (redirect, login-HTML 200, 404, 405, 429) as `unsupported` instead of `valid: true` for providers whose registry `baseUrl` is a conversation/completion endpoint rather than a real API root (#7857) +- fix(providers): copilot-m365-web now fails loudly on a fully-empty turn instead of a silent `stop`, and the enterprise tier threads its own `optionsSets`/`tone`/`allowedMessageTypes` into the chat invocation instead of only changing the WS URL (#7858, #7870) +- fix(providers): Gemini Web connection test now accepts the expected 302 redirect instead of failing with 'Redirect blocked' (#7859) +- fix(cli): translate missing better-sqlite3 native bindings error into actionable `omniroute runtime repair` guidance in `reset-password`/setup CLI commands (#7868) +- fix(auth): restore `HEALTHCHECK_BATCH_SIZE` env-var configurability of the OAuth token-health-check sweep batch size, dropped as a hardcoded constant by #7719 (#7875) +- **fix(opencode-plugin):** the official `@omniroute/opencode-plugin` now accepts an optional `managementReadToken` for management-plane catalog GETs while keeping inference requests on the connected `apiKey` — existing configurations continue to fall back to `apiKey`, and MCP token selection remains independent. (thanks @RaviTharuma) ([#7884](https://github.com/diegosouzapw/OmniRoute/issues/7884)) +- **fix(dashboard):** Provider Quota cutoff inputs preserve unsaved values across quota refreshes instead of reverting while the operator is typing ([#7889](https://github.com/diegosouzapw/OmniRoute/issues/7889)). +- **fix(sse):** Anthropic requests that reject a completed historical thinking signature now retry once with only that historical thinking omitted, while valid requests and active tool-use cycles remain unchanged. ([#7906](https://github.com/diegosouzapw/OmniRoute/pull/7906)) +- **Chat Core**: client aborts that reject the upstream fetch with a raw string reason (e.g. `request_signal_aborted`, `Client disconnected`) are now reported as `499 Request aborted` in the response, request logs, and usage records instead of `FAILED 502 / Bad Gateway`. Follow-up to #7908 for #7907. +- **fix(resilience):** Client-aborted requests are now treated as client lifecycle events rather than provider failures. They no longer cool down the serving connection or feed the provider circuit breaker, so a client that cancels a stream mid-flight (a routine occurrence with Claude Code) can no longer mark healthy accounts unavailable. Genuine upstream failures are still counted. ([#7907](https://github.com/diegosouzapw/OmniRoute/issues/7907)) +- fix(cli): spawn the win32 `opencode.cmd` shim with `shell:true` in `omniroute setup opencode --auth` to avoid the Node `spawnSync EINVAL` hardening error (#7913) +- fix(dashboard): correct "Block extra Claude usage" toggle copy to describe the connection-quarantine/fallback behavior it actually performs, instead of the non-existent display-dedup behavior it previously described (en/az/zh-CN/zh-TW/vi/pl) (#7918) +- **fix(autostart):** Windows auto-start no longer flashes a console window — writes a `.vbs` launcher to the Startup folder instead of the `HKCU\Run` registry key, adopting the same approach as 9Router ([#7925](https://github.com/diegosouzapw/OmniRoute/pull/7925)) +- **fix(providers):** perplexity-web now detects the `advanced_models_quota_low` upsell surfaced when a stream never materializes answer text, returning HTTP 429 with `reset_seconds`/`Retry-After` instead of a silent empty-content error, and reconstructs plan-goal reasoning from RFC-6902 diff-patched `plan_block` frames (live multi-step streams), not just materialized ones ([#7930](https://github.com/diegosouzapw/OmniRoute/pull/7930)) — thanks @artickc +- fix(sse): parse Gemini 429 RetryInfo.retryDelay / "please retry in Ns" so model lockout honors the short upstream hint instead of falling back to a ~19h until-midnight cooldown (#7940) +- fix(electron): resolve macOS Helper by binary name to remove second inert Dock icon (#7941) +- **fix(providers):** iFlytek Spark (`iflytek`, `sparkdesk`) now target the OpenAI-compatible host `spark-api-open.xf-yun.com/v1`; the previous `spark-api.xf-yun.com` is the WebSocket host and rejects bearer auth ([#7942](https://github.com/diegosouzapw/OmniRoute/pull/7942)) — thanks @FenjuFu +- fix(api): classify `/api/acp/agents` as loopback-only to close an RCE-via-tunnel gap in the ACP custom-agent registry (#7948) +- fix(cli): stop double-prefixing combo model ids in the opencode plugin's static provider catalog (#7976) +- fix(providers): route noauth opencode-zen connections through their assigned proxy ([#7993](https://github.com/diegosouzapw/OmniRoute/issues/7993)) +- fix(providers): refresh duckduckgo-web free model catalog to Duck.ai's current wire ids, fixing 400 ERR_BAD_REQUEST (#8000) +- fix(providers): repoint the zai-web executor at chat.z.ai's current v2 chat-completions endpoint, fixing model-independent 404s (#8014) +- fix(sse): bound the Codex SSE peek/passthrough body reads with a per-read timeout so a silently stalled upstream body settles in FETCH_BODY_TIMEOUT_MS instead of hanging ~15min and returning a generic 502 (#8020) +- fix(sse): replace spoofable `.includes()` PromptQL issuer check with hostname comparison (#8029) +- **fix(providers):** path-shaped multimodal model ids (e.g. `cp/cline-pass/kimi-k3`) resolve native vision via leaf/registry metadata instead of triggering Vision Bridge ([#8032](https://github.com/diegosouzapw/OmniRoute/issues/8032)) — thanks @Prudhvivuda +- fix(cli): merge Node's own bin dir into the CLI healthcheck spawn PATH so npm-shebang tools like codex resolve under a minimal launcher PATH (#8036) +- **fix(sse):** Bound forwarded upstream response headers so large provider metadata cannot turn successful streaming requests into reverse-proxy errors ([#8041](https://github.com/diegosouzapw/OmniRoute/pull/8041)) — thanks @insoln +- fix(db): register SIGHUP handler and stop force-killing the server on win32 stop paths so storage.sqlite's WAL gets checkpointed on shutdown (#8045) +- fix(oauth): warn instead of silently opening an unreachable localhost:1455 redirect for Codex/xAI/Grok CLI OAuth when the dashboard is reached from a LAN IP (#8046) +- **fix(sse):** run the prompt-compression pipeline per turn in the Codex Responses WebSocket bridge instead of skipping it entirely — a reused WebSocket connection now re-runs `prepare()` (auth/policy/memory/reasoning-routing/compression) for every logical `response.create` turn, not just the first (#8052) +- **fix(oauth):** Refreshing the token on an email-less OAuth connection (e.g. GitHub Copilot, whose identity lives under `providerSpecificData`) no longer creates a duplicate connection. `persistOAuthConnection` gated its whole dedup behind `if (tokenData.email)`, so the explicit `connectionId` passed on refresh was discarded and a new connection was created every time; the connectionId is now honored regardless of email, and email dedup only applies when a non-empty email is present. ([#8059](https://github.com/diegosouzapw/OmniRoute/issues/8059)) +- fix(routing): anchor quota routing cache on globalThis so cross-chunk reads/writes stay consistent (#8065) +- **fix(providers):** add the missing `poe` REGISTRY entry so built-in Poe model discovery resolves a base URL instead of failing with "No base URL configured for provider" ([#8082](https://github.com/diegosouzapw/OmniRoute/issues/8082)) +- fix(translator): set `status: "completed"` on translated OpenAI Responses `input` items so strict Responses-compatible upstreams stop rejecting them with 400 MissingParameter input.status (#8083) +- fix(sse): give keyless Pollinations image requests the same anonymous fingerprint-pool fallback the chat path already uses, instead of a real upstream 401 (#8085) +- fix(sse): stop Codex/Responses sanitizer from turning system/developer image_url parts into invalid output_text (#8089) +- fix(cli): surface the real spawn error (err.code/path/syscall/message) in the process supervisor instead of silently swallowing it on a child spawn failure (#8091) +- **fix(antigravity):** preserve request/tool fidelity, make credits modes explicit, and separate runtime endpoints from discovery/bootstrap ([#8098](https://github.com/diegosouzapw/OmniRoute/pull/8098)) — thanks @nguyenha935 +- fix(dashboard): clamp provider-cooldown min/max ms to their field bounds before Save so an out-of-range typed value can never reach the resilience settings API (#8107) +- fix(providers): filter unsupported family-fallback candidates against the provider catalog (#8134) +- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8136](https://github.com/diegosouzapw/OmniRoute/issues/8136)) +- fix(backend): word-boundary-safe tool-result truncation in lite compression mode (#8169) +- fix(api): narrow claudeClassifierCompat auto trigger so stop_sequences alone no longer short-circuits (#8189) +- fix(providers): carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8200](https://github.com/diegosouzapw/OmniRoute/issues/8200)) +- fix(gemini): drop HARM_CATEGORY_CIVIC_INTEGRITY from the default Gemini safety settings (#8231) +- **fix(dashboard):** Normalize Codex client URLs, restore the analytics input-bar color, resolve OAuth modal TypeScript regressions, synchronize the documented compression-engine count, and sanitize Muse Spark fetch errors ([#8233](https://github.com/diegosouzapw/OmniRoute/pull/8233)) — thanks @nguyenha935 +- fix(providers): classify per-model-quota 403 and DEGRADED 400 as model-unhealthy in checkFallbackError (#8247, #8248) +- **fix(providers):** reconcile Kimi K3 vision metadata when synced `attachment=false` contradicts image/video `modalities_input`, so `supportsVision`, `attachment`, and exposed modalities agree ([#8250](https://github.com/diegosouzapw/OmniRoute/issues/8250)) — thanks @Prudhvivuda +- **fix(providers):** the Providers page Learn more button now opens the maintained GitHub documentation instead of the retired `docs.omniroute.io` page ([#8284](https://github.com/diegosouzapw/OmniRoute/pull/8284)) - thanks @KaynXu +- fix(api): fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8295](https://github.com/diegosouzapw/OmniRoute/issues/8295)) +- **fix(runtime):** sanitize Muse Spark fetch failures before logging and resolve the sql.js WASM asset without the unexported package metadata subpath ([#8298](https://github.com/diegosouzapw/OmniRoute/pull/8298)) — thanks @backryun +- **fix(sse):** Combo middleware preserves OpenAI Responses request bodies and maps combo system overrides to `instructions`, preventing Responses-native fallbacks from receiving an unsupported `messages` parameter. ([#8310](https://github.com/diegosouzapw/OmniRoute/pull/8310)) — thanks @ridho9 +- fix(api): accept the current compatible-provider connection id scheme in the models test route (#8326) +- fix(api): stop leaking the internal provider UUID in /v1/models and honor the configured prefix (#8327) +- fix(dashboard): show custom provider_nodes providers in the Topology view instead of only AI_PROVIDERS (#8328) +- fix(api): stop the 2000-token safety buffer from inflating usage.prompt_tokens in the client response (#8331) +- fix(backend): keep combo routing from dispatching image requests to text-only targets (#8332) +- fix(sse): strip third-party-agent signals from the Hermes system prompt that trigger Anthropic 400 extra-usage (#8350) +- **fix(i18n):** Restore brand/model proper nouns (Claude, OpenAI, Anthropic, Gemini, MiniMax, etc.) in zh-CN and zh-TW — replace Chinese phonetic/translation forms (克劳德/打开Ai/人择/双子座) with original English, unify "provider" translation to "供应商/供應商", and apply zh-TW localized terminology (網路/設定/檔案/新增/啟用/搜尋/儲存) instead of mainland defaults (#8355 — thanks @ikelvingo). +- fix(api): estimate inline base64 image tokens instead of counting the data URL as text so it does not falsely exceed the context window (#8368) +- fix(backend): stop prompt-cache affinity from silently reordering an explicit priority combo across models (#8370) +- fix(api): accept a missing status query-param on GET /api/plugins instead of rejecting null with Invalid status value (#8374) +- fix(resilience): treat an unreachable-proxy ECONNREFUSED as a circuit-breaker event so combo fails over instead of hitting the 503 max-retry limit (#8376) +- fix(backend): make disabling the global per-key proxy toggle override existing per-key proxy assignments (#8385) +- fix(dashboard): persist compression engine detail settings (Headroom / session dedup / CCR) instead of dropping them on save (#8388) +- fix(plugins): fire registered+active plugin hooks (onRequest/onResponse/onError) during proxying instead of never invoking them (#8395) +- fix(resilience): cap the connection cooldown after a 429 burst so combo fallback is not blacked out past the real rate-limit window (#8396) +- fix(api): reach synced model_capabilities rows for canonical provider ids that only appear as an alias in MODELS_DEV_PROVIDER_MAP, e.g. codex/claude (#8429) +- fix(providers): stop marking a multi-quota-window provider exhausted when only some windows are depleted (LIMIT-200 snapshot eviction drops idle healthy windows) (#8431) +- fix(backend): compute AgentBridge diagnose `dnsConfigured` per-agent instead of hard-coded to Antigravity hosts (#8466) +- **fix(providers):** OpencodeExecutor honors Extra API Keys rotation via `resolveEffectiveKey` (empty primary + extras no longer omit Authorization) ([#8467](https://github.com/diegosouzapw/OmniRoute/issues/8467)) — thanks @Prudhvivuda +- fix(sse): stop combo's "all targets failed" response from attaching one target's retry-after window to an unrelated target's error message (#8486) +- **fix(backend):** capability filters fail closed when every combo target is incompatible, with opt-in `compatFilterFailOpen` ([#8488](https://github.com/diegosouzapw/OmniRoute/issues/8488)) — thanks @Prudhvivuda +- fix(providers): persist a runtime-discovered Antigravity projectId back onto the connection so it survives token refreshes and restarts instead of being rediscovered or lost (#8491) +- fix(cli): `backup create` / `backup auto enable` — option shadowing by the parent `backup` command removed; all flags (`--cloud`, `--encrypt`, `--retention`, `--name`, `--exclude`, `--key-file`) now reach the subcommand handler with their actual values instead of being silently discarded ([#8512](https://github.com/diegosouzapw/OmniRoute/issues/8512)) +- **fix(dashboard):** Endpoint/API base URL display honors `OMNIROUTE_BASE_PATH` (e.g. `https://host/omniroute/v1` instead of `https://host/v1` under reverse-proxy subpath deploys) ([#8514](https://github.com/diegosouzapw/OmniRoute/pull/8514)) — thanks @rqzbeh +- **fix(client):** Absolute `fetch("/api/...")` and `EventSource("/api/...")` honor `OMNIROUTE_BASE_PATH` under reverse-proxy subpath deploys (no domain-root 404s for dashboard health/SSE) ([#8515](https://github.com/diegosouzapw/OmniRoute/pull/8515)) — thanks @rqzbeh +- fix(cli): create `~/.cache` (and set `XDG_CACHE_HOME`) before Next.js loads on Android/Termux so `getCacheDirectory()` no longer aborts with `Unsupported platform: android`, which previously left every request as a silent HTTP 500 after the CLI still looked "running" (#8519) +- fix(api): surface a non-blocking warning + startup scan when a combo name shadows a real model id, instead of silently routing with zero signal (#8530) +- **fix(kiro):** support profileless Builder ID quota, preserve CLI auth identity, stabilize social OAuth polling, and use the live model catalog ([#8565](https://github.com/diegosouzapw/OmniRoute/pull/8565)) — thanks @nguyenha935 +- fix(test): isolate `context-manager` unit tests on a temp `DATA_DIR` so `getTokenLimit` resolves against the registry fallback instead of the developer's local models.dev sync ([#8568](https://github.com/diegosouzapw/OmniRoute/issues/8568)) +- **fix(quality):** `check:file-size --update` now removes baseline entries that already fit the new-file cap even when LOC equals the frozen value (`redundant` path) — closes the #8584 gap where at-cap entries were stuck forever ([#8589](https://github.com/diegosouzapw/OmniRoute/pull/8589)) — thanks @MumuTW +- **fix(sse):** restore Task-Aware Routing config from `settings.taskRouting` at boot and keep it on `globalThis` so multi-graph imports share one store — stops the feature silently reverting to disabled on every restart (#8601) ([#8604](https://github.com/diegosouzapw/OmniRoute/pull/8604)) — thanks @MumuTW +- **fix(sse):** task-aware routing defaults use `auto/*` intents instead of hardcoded provider/model ids (#8602), and the longest-pattern-first fitness table match that landed upstream in 9f5be229b gains a direct regression guard, so rows like `gpt-4o-mini` cannot be shadowed by `gpt-4o` again (#8603) ([#8605](https://github.com/diegosouzapw/OmniRoute/pull/8605)) — thanks @MumuTW +- **fix(providers):** keep registered OpenCode Go effort aliases in the Playground catalog when synced base models are present, and preserve Hunyuan3's 256K context metadata for combo routing ([#8610](https://github.com/diegosouzapw/OmniRoute/pull/8610)). +- **fix(resilience):** report local request-queue expirations as service-unavailable capacity failures instead of upstream 502 errors, preventing incorrect provider cooldowns and same-target retries ([#8613](https://github.com/diegosouzapw/OmniRoute/pull/8613)). +- **fix(docker):** Honor `OMNIROUTE_BASE_PATH` behind reverse-proxy subpaths by baking the subpath into the standalone bundle at image build time (`ARG OMNIROUTE_BASE_PATH`) and patching the published root-path image at container start (`scripts/docker/ensure-docker-base-path.mjs`); healthcheck probes the prefixed `/api/monitoring/health` route ([#8615](https://github.com/diegosouzapw/OmniRoute/pull/8615)) — thanks @DinonowDev +- **fix(resilience):** recover a wedged local request limiter after an idle-capacity queue expiry by retrying the request on a fresh limiter ([#8616](https://github.com/diegosouzapw/OmniRoute/pull/8616)). +- **fix(providers):** Kimi Coding billing-cycle quota errors now recover automatically at the cached reset instead of remaining unavailable ([#8632](https://github.com/diegosouzapw/OmniRoute/pull/8632)) — thanks @glazec +- **fix(oauth):** show GitLab Duo OAuth app / env setup instructions in the Add Connection modal _before_ authorize, using a shared recipe with catalog `authHint` and the authorize-route error fallback (#8688) +- **fix(sse):** combo compression-limit resolution falls back to `ResolvedComboTarget.provider` when `modelStr` lacks a `provider/` prefix, so `getTokenLimit` no longer crashes with `null.toUpperCase()` (#8716) — thanks @DinonowDev +- **fix(db):** fall back to Node's built-in SQLite driver when better-sqlite3 is unavailable, while preserving read-only and existing-file safeguards ([#8724](https://github.com/diegosouzapw/OmniRoute/pull/8724)) — thanks @epsilonode +- **fix(resilience):** keep missing request resources such as Files API ids from triggering model-family fallback, model lockout, or provider/account cooldown (thanks @wilsonicdev) ([#8756](https://github.com/diegosouzapw/OmniRoute/pull/8756)) +- **fix(api):** `GET /v1/models` no longer rebuilds the whole catalog on almost every request. The response cache added by [#6408](https://github.com/diegosouzapw/OmniRoute/pull/6408) memoized the body for `modelCatalogCacheTtlMs`, defaulted to 1500 ms — shorter than a single build (~49 s for a 1.3 MB / 2645-model catalog on a real install), so any two requests more than 1.5 s apart both missed the fresh window and the second fell into a stale-while-revalidate rebuild that pins the single-threaded event loop, delaying even the "immediate" stale response. The default is now 60 s, matching the ceiling the settings schema already allows for the override. A short TTL was redundant with the cache's existing invalidation: `invalidateDbCache()` bumps the catalog cache version on every settings/connections/combos/pricing write, so post-write freshness never depended on the TTL. ([#8833](https://github.com/diegosouzapw/OmniRoute/pull/8833)) +- **GHE Copilot**: OpenAI-native models now route to `/responses` instead of failing with `model "..." is not accessible via the /chat/completions endpoint` — `gpt-5.4-mini`, `gpt-5.3-codex`, `mai-code-1-flash` and `oswe-vscode-prime` carry `targetFormat: "openai-responses"`, and `gpt-5.6-sol`/`terra`/`luna` are registered. Claude and Gemini models under `ghe-copilot` keep using `/chat/completions` ([#8835](https://github.com/diegosouzapw/OmniRoute/pull/8835)) — thanks @hppsc1215 +- **CLI**: `omniroute launch` no longer truncates pass-through arguments at the first space on Windows — each argument is escaped for cmd.exe (CRT argv rules plus a double caret pass, required because `claude.cmd` re-parses `%*`). A non-zero child exit also stops aborting the process with a libuv assertion: the exit code is set on `process.exitCode` so the loop drains the inherited stdio handles first ([#8837](https://github.com/diegosouzapw/OmniRoute/pull/8837)) — thanks @sumanxg +- **Providers**: Codex GPT-5.6 Sol/Terra/Luna report the current upstream context window of 272000 instead of a stale 372000, so catalog consumers stop compacting past the Codex backend real input limit. Public OpenAI API GPT-5.6 metadata is unchanged ([#8838](https://github.com/diegosouzapw/OmniRoute/pull/8838)) — thanks @TitoTFP +- **Antigravity**: a token refresh now recovers a missing `projectId` instead of leaving the connection stuck on 422 — when the initial OAuth exchange fails to populate it (network timeout, account not yet onboarded to Gemini Code Assist), `refreshCredentials` retries discovery via `ensureAntigravityProjectAssigned` and persists the result, mirroring the runtime `transformRequest` path. Best-effort: a failed discovery leaves the next request to retry ([#8842](https://github.com/diegosouzapw/OmniRoute/pull/8842)) — thanks @HouMinXi +- **CI**: `check:tracked-artifacts` raises the `git ls-files` stdout ceiling to 64 MiB — the default 1 MiB `execFileSync` buffer had only ~6 KB of headroom against the tracked tree, and overflowing it throws ENOBUFS in the pre-commit hook, breaking `git commit` for everyone working the repo ([#8844](https://github.com/diegosouzapw/OmniRoute/pull/8844)) +- **OAuth**: `ANTIGRAVITY_OAUTH_CLIENT_TYPE=web` lets a remote deployment use a Google Web application OAuth client, upgrading the loopback redirect to `OMNIROUTE_PUBLIC_BASE_URL` instead of leaving the operator to hand-edit the callback URL. Opt-in and requires custom credentials — unset or `desktop` keeps the existing loopback behaviour untouched ([#8845](https://github.com/diegosouzapw/OmniRoute/pull/8845)) — thanks @HouMinXi +- **fix(executors):** Vertex AI now routes current-generation Claude models (`claude-sonnet-4-6`, `claude-haiku-4-5`, etc.) through the partner endpoint instead of misrouting them as Google-publisher models ([#8852](https://github.com/diegosouzapw/OmniRoute/pull/8852)) — thanks @wgordon17 +- **CLI**: `omniroute launch-codex` no longer corrupts the codex argv on Windows — every invocation was affected, not just multi-word ones, because `buildCodexProviderArgs()` injects `-c` flags whose TOML values are quoted and cmd.exe stripped those quotes. The escaping helper introduced for `launch` is now shared from `bin/cli/utils/winShellArgs.mjs` and applied to the whole codex argv. A non-zero child exit also sets `process.exitCode` instead of calling `process.exit()`, which aborted with a libuv assertion while the inherited stdio handles were still closing ([#8856](https://github.com/diegosouzapw/OmniRoute/pull/8856)) — thanks @sumanxg +- **Providers**: AGY model sync now discovers newly announced chat models from the live Antigravity catalog while filtering internal and tab-completion-only models, with the bundled catalog retained as an offline fallback +- fix(security): bound JWT-extraction regexes in adobeFireflyClient to prevent polynomial ReDoS (CodeQL #754/#755/#756) +- Fixed every non-streaming Codex (ChatGPT-account) chat request failing with `[502]: Response body is already used (reset after 1m)`: `peekCodexSseTransientError` re-acquired a reader on the upstream `response.body` after `releaseLock()` to continue draining it, which throws on undici. It now keeps the single reader it already holds. The thrown TypeError was also being mis-classified as a 60s rate limit (cooldown + circuit breaker) — that misfire disappears with the double-read fixed. +- **Logging**: a broken stdout/stderr pipe no longer drives a self-sustaining log-flood loop — `consoleInterceptor` attaches `'error'` listeners to both std streams so an async EPIPE stops becoming an `uncaughtException` the framework re-logs through the patched console (measured 3,387 uncaught exceptions in 1.5s, now 0), non-EPIPE stream errors are re-raised so conditions like `ENOSPC` stay fatal, `structuredLogger`'s raw stderr writes skip a stream already known dead, interceptor disk writes are rate limited at `error` level only so ordinary logging is untouched, and a log directory removed at runtime is recreated instead of silently ending file logging (#8181) +- docs: correct three stale references caught by the fabricated-docs gate (`/api/version` → `/api/monitoring/health`, migration `125_` → `126_reasoning_routing_rules.sql`) +- Fix the Turbopack `next build` breaking with "Module not found: Can't resolve 'child_process'": the Kimi sponsor banner's client-side version gate imported semver helpers from `versionCheck.ts` (a server module with a top-level `child_process` import), dragging Node built-ins into the browser bundle. The pure `isNewer`/`normalizeVersion` helpers now live in a dependency-free `versionCompare.ts`; `versionCheck.ts` re-exports them for back-compat. +- Fix `mitm-dnsConfig` unit tests failing when the suite runs as root (or with `OMNIROUTE_NO_SUDO` / no `sudo` installed): they hardcoded `sudo` as the spawned command, but `resolveSudoSpawn()` deliberately strips the `sudo -S` prefix in those environments (#6122). The tests now assert the effective invocation (`tee -a `, elevated or not). +- muse-spark-web: the WebSocket 401 auth-failure message now names the live `ecto_1_sess` cookie (the retired `abra_sess` name was dropped in the GraphQL→WS migration), so users know which cookie to re-paste. +- Harden the Notion web provider thread-session cache against cross-tenant access: the cache is now namespaced per caller (hash of the caller's cookie) instead of only by Notion space id, and client-supplied thread ids are validated as real Notion UUIDs before use — closing an IDOR where two users of the same Notion space could pin/read each other's thread (#7900 security review). +- fix(security): OIDC login gate now requires `email_verified` before honoring the email claim against the allowlist (an unverified IdP email matching an allowlisted address no longer bypasses the gate), and error redirects resolve against the parsed request URL instead of the raw Host header +- **Build**: the packed tarball boots again — #7191's `../../src/…runtimeTimeouts.ts` import in `standalone-server-ws.mjs` escaped the package after the dist-root copy (`ERR_MODULE_NOT_FOUND` on every boot, #7065 class, caught live by the new `check:pack-boot` gate); the helper now lives in the shipped sibling `main-server-timeouts.mjs` (parity-tested against the canonical TS implementation) and the closure test bans package-escaping `../` imports in npm-shipped wrappers +- **Packaging**: new `check:pack-boot` gate packs the real npm tarball, installs it into a clean prefix (postinstall runs for real) and boots the installed CLI until `/api/monitoring/health` returns 200 with the packed version — the runtime gate that structure checks could not provide (3 releases shipped boot-crashing tarballs with green packaging lists: tls-options/3.8.41, #7040, #7065). Wired into the CI `package-artifact` job and `check:release-green --with-build` +- **Packaging**: pack-artifact closure tests now cover EVERY npm-shipped dist wrapper (derived from `EXTRA_MODULE_ENTRIES`) and the `bin/omniroute.mjs` CLI entry — including dynamic `import()` and `require()` forms the original server-ws test missed — requiring each local import in both the prepublish prune allowlist and `check:pack-artifact`; `bin/cli/data-dir.mjs` and `bin/cli/utils/storageKeyProvision.mjs` are now required tarball paths (#7065 class hardening, WS1.1) +- **fix(cli):** CLI detection now refreshes stale cached results, reports discovered versions, and checks the Continue `cn` binary instead of assuming it is installed. +- **fix(docker):** Podman deployment guidance now distinguishes local Linux rootless engines from macOS/Windows Podman Machine, corrects Quadlet and local-build instructions, and avoids unsupported remote-client `podman unshare` hints ([#8497](https://github.com/diegosouzapw/OmniRoute/issues/8497)). +- **fix(ui):** Theme React Flow controls correctly in dark mode, improve idle connector contrast, and localize the provider topology legend. +- **fix(plugins):** the generated plugin host script is now deleted synchronously — an async `rm()` lost the race against process exit, so every plugin load under `node --test --test-force-exit` leaked one temp `.mjs` into the OS temp dir; two plugin manager tests also stopped leaking child processes +- **fix(compression):** the Headroom SmartCrusher tabular-compaction guard now also skips `role: "developer"` messages, not just `role: "system"` — Codex CLI sends its instructions/tool-schema turn as `developer` (the Responses-API equivalent of `system`), so an embedded JSON array (e.g. an `update_plan` example) could get tabular-compacted, corrupting the model's tool-calling instructions and breaking Codex CLI plan mode. (thanks @SingCJ) +- **Skills**: register `cli-skill-collector` in the agent-skills catalog (types union, curated entry, CLI id list) — #6294 shipped the `skills/cli-skill-collector/` directory without the catalog registration, so it was unreachable via the API and Integration CI failed on the catalog-integrity test; counts aligned (44 API+CLI, 45 with config) +- **fix(responses):** Make Responses API to Chat Completions downgrades provider-neutral and loss-aware. Tools declared through `additional_tools` are preserved, structured output and `allowed_tools` are translated, refusal history is normalized, unsupported input item types fail explicitly instead of disappearing, and Responses-only execution/cache fields no longer leak to strict Chat endpoints. +- **fix(stream):** Responses API clients (`/v1/responses`) no longer receive a stray `` text delta at the start of the assistant message on Claude-format upstreams (observed with kimi-coding). The `` close marker (#4633) exists for Chat Completions clients that scan content for it; Responses API clients receive reasoning as structured reasoning items, so the marker is now always suppressed on that path — including the GLM and zed-hosted executors, which do their own Claude→OpenAI translation. +- fix(security): bump adm-zip to ^0.6.0 (dev transitive via promptfoo/onnxruntime-node) to clear the crafted-ZIP 4GB-allocation advisory, and tighten mitm DNS test host assertions to exact/suffix matching (CodeQL js/incomplete-url-substring-sanitization) +- chore(deps): bump fast-uri≥3.1.3, hono≥4.12.27, @hono/node-server≥2.0.5, body-parser≥2.3.0 to clear 7 Dependabot alerts +- chore(deps): bump dompurify≥3.4.12, fast-xml-parser≥5.10.1, sharp≥0.35.0 to clear 3 Dependabot alerts +- fix(quality): register the two covering unit tests missing from stryker tap.testFiles (#6846, #7333) +- fix(auth): restore the TICK_MS constant dropped by #7719, which made initTokenHealthCheck() throw a ReferenceError at startup +- fix(guardrails/chat): do not whole-request-reroute Vision Bridge away from credentialed models (e.g. combo target zai/glm-5.2 or grok-cli → opencode-zen noauth 401); align body.model with X-Route-Model so post-guardrail cannot undo the routing header +- **Providers**: yuanbao-web no longer forwards a foreign single cookie pair upstream — `buildYuanbaoCookie` only trusts `hy_user`/`hy_token` extractions the input explicitly names, so a missing session token now fails fast with the local 401 guidance instead of a live Tencent round-trip +### 📚 Docs + +- **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) +- **docs(troubleshooting):** document Avast/AVG README.md false positive (#5946) ([#7295](https://github.com/diegosouzapw/OmniRoute/pull/7295)) +- **docs(perf):** add per-endpoint p50/p95/p99 latency + cost budget reference ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **docs:** refresh revoked Discord invite + WhatsApp Brasil link ([#7604](https://github.com/diegosouzapw/OmniRoute/pull/7604)) +- **docs(readme):** animated SVG for the 4-tier auto-fallback cascade ([#7615](https://github.com/diegosouzapw/OmniRoute/pull/7615)) +- **docs:** sync provider count to 259 (unblocks docs-counts strict gate) ([#7616](https://github.com/diegosouzapw/OmniRoute/pull/7616)) +- **docs(readme):** animate pool + combo ASCII blocks as SMIL SVG diagrams ([#7626](https://github.com/diegosouzapw/OmniRoute/pull/7626)) +- **docs(readme):** animate CLI command list + compression flow as SMIL SVGs ([#7637](https://github.com/diegosouzapw/OmniRoute/pull/7637)) +- **docs(readme):** replace free-tier budget mockup with animated SMIL card ([#7665](https://github.com/diegosouzapw/OmniRoute/pull/7665)) +- **docs(readme):** standardize all README tables to full content width ([#7666](https://github.com/diegosouzapw/OmniRoute/pull/7666)) + +- **docs:** fix three stale references failing the fabricated-docs gate ([#7728](https://github.com/diegosouzapw/OmniRoute/pull/7728)) +- **docs(readme):** unified animated card system — audited v3.8.49 numbers, style contract across all cards, 5 new cards + rebuilt terminal ([#7769](https://github.com/diegosouzapw/OmniRoute/pull/7769)) +- **docs(readme):** add Kimi (Moonshot AI) official supporter section ([#7770](https://github.com/diegosouzapw/OmniRoute/pull/7770)) +- **docs(getting-started):** reorder Verify It Works before IDE/CLI setup + add examples ([#7790](https://github.com/diegosouzapw/OmniRoute/pull/7790)) — thanks @swingtempo +- **docs(readme):** audit every number against the live code + refresh contributors and acknowledgments ([#7795](https://github.com/diegosouzapw/OmniRoute/pull/7795)) +- **docs(readme):** evolve supporter section into sub2api-style Sponsors section ([#7799](https://github.com/diegosouzapw/OmniRoute/pull/7799)) +- **docs(readme):** contributors 360+ -> 350+ (audited) ([#7803](https://github.com/diegosouzapw/OmniRoute/pull/7803)) +- **docs(i18n):** refresh Polish README and fix relative links ([#7807](https://github.com/diegosouzapw/OmniRoute/pull/7807)) — thanks @leszek3737 +- **docs:** add general Web Cookie provider setup guide ([#7881](https://github.com/diegosouzapw/OmniRoute/pull/7881)) — thanks @arpit-jaiswal-dev +- **docs(guides):** document Kaspersky PDM behavioral false positive on the Desktop installer (#7903) ([#7923](https://github.com/diegosouzapw/OmniRoute/pull/7923)) +- **docs:** document npm install ERESOLVE/peer/deprecated warnings as harmless (fixes #7951) ([#7988](https://github.com/diegosouzapw/OmniRoute/pull/7988)) — thanks @Dingding-leo +- **docs:** fix Docker IPv6 connection reset with -p 127.0.0.1 bind (fixes #7722) ([#7989](https://github.com/diegosouzapw/OmniRoute/pull/7989)) — thanks @Dingding-leo +- **docs(readme):** Kimi partner tracking links (aff=omniroute) + first-Brazilian-project line + disclosure ([#8028](https://github.com/diegosouzapw/OmniRoute/pull/8028)) +- **docs:** add AgentRouter multi-provider routing troubleshooting ([#8049](https://github.com/diegosouzapw/OmniRoute/pull/8049)) — thanks @leninejunior +- **docs(security):** correct prompt-injection severity table + heuristic-limitations disclaimer (#8097) ([#8113](https://github.com/diegosouzapw/OmniRoute/pull/8113)) — thanks @rafaumeu +- **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal +- **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX +- **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +### 🧪 Tests & Quality + +- **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) +- **test(dashboard):** dedicated regression guard for #6815 density guarantee ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **test(ci):** make #6634 selfref guard hermetic — read file from disk, no git ref ([#7327](https://github.com/diegosouzapw/OmniRoute/pull/7327)) +- **test(ci):** mock route bridge surfaces error message, not raw stack ([#7354](https://github.com/diegosouzapw/OmniRoute/pull/7354)) +- **test(ci):** static body in codex e2e mock route bridge (CodeQL #737) ([#7558](https://github.com/diegosouzapw/OmniRoute/pull/7558)) +- **test(ci):** exact-line assert in grok-build config test (CodeQL #740/#741) ([#7628](https://github.com/diegosouzapw/OmniRoute/pull/7628)) + +- **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan +- **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) +- **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +### 🔧 Chores / CI + +- **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) +- **chore(ci):** gate hygiene — secrets baseline 0, semgrep drop, hadolint (WS6/D3 + WS1.7) ([#7099](https://github.com/diegosouzapw/OmniRoute/pull/7099)) +- **chore(ops):** runner-box janitor + operations runbook (WS3.3) ([#7115](https://github.com/diegosouzapw/OmniRoute/pull/7115)) +- **chore(ci):** promote test:vitest:ui to blocking (suite green after #7127) ([#7147](https://github.com/diegosouzapw/OmniRoute/pull/7147)) +- **chore(ci):** stop dependabot proposing typescript majors — peer-blocked by typescript-eslint ([#7306](https://github.com/diegosouzapw/OmniRoute/pull/7306)) +- **chore(release):** script the 0a.0b PR re-home with a verified read-back ([#7312](https://github.com/diegosouzapw/OmniRoute/pull/7312)) +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers ([#7326](https://github.com/diegosouzapw/OmniRoute/pull/7326)) +- **chore(ci):** make the Electron Windows leg advisory with bash stderr capture (first-run failure diagnosis) ([#7340](https://github.com/diegosouzapw/OmniRoute/pull/7340)) +- **chore(deps):** bump actions/setup-node from 6 to 7 ([#7348](https://github.com/diegosouzapw/OmniRoute/pull/7348)) +- **chore(deps):** bump codecov/codecov-action ([#7350](https://github.com/diegosouzapw/OmniRoute/pull/7350)) +- **ci(release-green):** add a main-green arm to detect when main goes red ([#7355](https://github.com/diegosouzapw/OmniRoute/pull/7355)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.0 to 4.37.1 ([#7641](https://github.com/diegosouzapw/OmniRoute/pull/7641)) +- **chore(deps):** bump github/codeql-action/init from 4.37.0 to 4.37.1 ([#7642](https://github.com/diegosouzapw/OmniRoute/pull/7642)) +- **chore(quality):** register #6672 test in stryker tap.testFiles (base-red unblock) ([#7652](https://github.com/diegosouzapw/OmniRoute/pull/7652)) +- **chore(release):** merge-train box-speed suite + --fast mode ([#7670](https://github.com/diegosouzapw/OmniRoute/pull/7670)) + +- **chore:** [defer] fix embedded CLIProxyAPI config handling ([#6877](https://github.com/diegosouzapw/OmniRoute/pull/6877)) — thanks @professional-ALFIE +- **chore:** [defer] fix(grok): align responses tool-call shape for grok models ([#6937](https://github.com/diegosouzapw/OmniRoute/pull/6937)) — thanks @CitrusIce +- **chore:** [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab ([#7251](https://github.com/diegosouzapw/OmniRoute/pull/7251)) +- **chore:** [defer] feat(combo): universal cooldown-aware retry & auto-strategy combo-ref guard ([#7301](https://github.com/diegosouzapw/OmniRoute/pull/7301)) — thanks @ViFigueiredo +- **chore:** Completing Arabic language ([#7686](https://github.com/diegosouzapw/OmniRoute/pull/7686)) — thanks @mustafa-phd +- **chore:** IC2: Cache provider connections by ID + provider nodes ([#7744](https://github.com/diegosouzapw/OmniRoute/pull/7744)) — thanks @oyi77 +- **chore:** [Emergency Fix] fix(build): repair release build blockers ([#7772](https://github.com/diegosouzapw/OmniRoute/pull/7772)) — thanks @backryun +- **chore:** [Part 1/3]refactor(qwen): replace legacy Qwen Code and remove OAuth provider ([#7866](https://github.com/diegosouzapw/OmniRoute/pull/7866)) — thanks @backryun +- **chore:** [Part 3/3] feat(qwen): add regional Alibaba and Qwen Cloud providers ([#7882](https://github.com/diegosouzapw/OmniRoute/pull/7882)) — thanks @backryun +- **chore:** Preserve supported Responses behavior in Chat translation ([#7894](https://github.com/diegosouzapw/OmniRoute/pull/7894)) — thanks @JxnLexn +- **chore:** Restore Responses API custom tool calls ([#7905](https://github.com/diegosouzapw/OmniRoute/pull/7905)) — thanks @JxnLexn +- **chore:** Hide internal reasoning replay placeholders ([#7912](https://github.com/diegosouzapw/OmniRoute/pull/7912)) — thanks @JxnLexn +- **chore(deps):** bump js-yaml, brace-expansion, shell-quote, tar (security) ([#7915](https://github.com/diegosouzapw/OmniRoute/pull/7915)) +- **chore:** i18n(zh-TW): complete Traditional Chinese (Taiwan) translation overhaul ([#8024](https://github.com/diegosouzapw/OmniRoute/pull/8024)) — thanks @lunkerchen +- **chore:** i18n: bring 40 locales to full parity with en.json ([#8031](https://github.com/diegosouzapw/OmniRoute/pull/8031)) — thanks @nguyenha935 +- **chore(deps):** resolve 7 open Dependabot alerts via npm overrides ([#8066](https://github.com/diegosouzapw/OmniRoute/pull/8066)) +- **chore(deps):** resolve 3 more Dependabot alerts (dompurify, fast-xml-parser, sharp) ([#8069](https://github.com/diegosouzapw/OmniRoute/pull/8069)) +- **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) +- **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark +- **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +### 🔀 Other + +- [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev +- [codex] Keep mode-pack weights consistent in auto fallback ranking ([#7008](https://github.com/diegosouzapw/OmniRoute/pull/7008)) — thanks @KooshaPari +- Explain effective auto-combo scoring weights ([#7087](https://github.com/diegosouzapw/OmniRoute/pull/7087)) — thanks @KooshaPari +- [needs-vps] fix(dashboard): add vision-capability toggle for custom OpenAI-compatible models ([#7124](https://github.com/diegosouzapw/OmniRoute/pull/7124)) +- [needs-vps] fix(dashboard): align onboarding tier content ([#7125](https://github.com/diegosouzapw/OmniRoute/pull/7125)) — thanks @Wibias +- Use OpenAI chunks for early chat keepalives ([#7136](https://github.com/diegosouzapw/OmniRoute/pull/7136)) — thanks @KooshaPari +- Fix Codex Responses compression analytics ([#7273](https://github.com/diegosouzapw/OmniRoute/pull/7273)) — thanks @JxnLexn +- Add cache-aligned Live Zone compression ([#7280](https://github.com/diegosouzapw/OmniRoute/pull/7280)) — thanks @JxnLexn +- Fix routed target request parameters ([#7323](https://github.com/diegosouzapw/OmniRoute/pull/7323)) — thanks @JxnLexn +- deps: bump electron from 43.1.0 to 43.1.1 in /electron ([#7349](https://github.com/diegosouzapw/OmniRoute/pull/7349)) +- deps: bump the development group with 8 updates ([#7351](https://github.com/diegosouzapw/OmniRoute/pull/7351)) +- deps: bump the production group across 1 directory with 12 updates ([#7352](https://github.com/diegosouzapw/OmniRoute/pull/7352)) +- Add per-connection Provider Quota visibility ([#7360](https://github.com/diegosouzapw/OmniRoute/pull/7360)) — thanks @JxnLexn +- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn +- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn +- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn +- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn +- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn +- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn +- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn + +- **refactor(sse):** extract per-provider token-refresh functions from tokenRefresh.ts ([#7817](https://github.com/diegosouzapw/OmniRoute/pull/7817)) +- **deps:** bump the production group with 8 updates ([#7897](https://github.com/diegosouzapw/OmniRoute/pull/7897)) — thanks @dependabot[bot] +- **deps:** bump the development group with 5 updates ([#7898](https://github.com/diegosouzapw/OmniRoute/pull/7898)) — thanks @dependabot[bot] +- **refactor(antigravity):** align official clients and callable catalog ([#8013](https://github.com/diegosouzapw/OmniRoute/pull/8013)) — thanks @backryun +- **refactor(compression):** extract resolveHeadroomDetail to keep dispatchCompression under the complexity gate ([#8058](https://github.com/diegosouzapw/OmniRoute/pull/8058)) +- **deps:** bump next from 16.2.10 to 16.2.11 ([#8235](https://github.com/diegosouzapw/OmniRoute/pull/8235)) — thanks @dependabot[bot] +### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) + +- **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. + +### 📝 Maintenance +- **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) +- **release:** `list-uncovered-commits.mjs` now unions the CHANGELOG scan window with `changelog.d/` fragment refs (filename `-` prefix + every `#N` in the body), so a commit covered only by a fragment is no longer reported as an uncovered reconciliation gap ([#6857](https://github.com/diegosouzapw/OmniRoute/issues/6857) via [#6878](https://github.com/diegosouzapw/OmniRoute/pull/6878)) +- **chore(ci):** stop dependabot from proposing `typescript` majors — `typescript-eslint` pins a hard peer upper bound (`>=4.8.4 <6.1.0`), so a TS 7 bump violates the peer and takes the whole toolchain red at once. #7068 grouped it with 6 harmless dev bumps and blocked all of them. TS majors now migrate intentionally, in their own PR. +- **maintenance(quality):** re-baseline `file-size` for two legitimately-grown files from the v3.8.49 owner-PR campaign — `src/app/api/usage/analytics/route.ts` 942→948 (180d/365d range cases, #7213) and `tests/unit/audio-transcription-handler.test.ts` added to `testFrozen` at 824 (Gladia STT test cases, #7603). Fast-gates PR→release skip `check:file-size`, so this only surfaced on re-sync; no behavior change. +- **fix(i18n):** backfill the four `usage.*` quota-visibility keys #7251 added to en.json into vi.json (hideQuotaRow, showQuotaRow, hiddenQuotaRowsLabel, quotaVisibilityUpdateFailed) — their absence left `__MISSING__` markers that failed `i18n-vi-completeness` on the release tip for every fresh PR run. +- **docs(codex):** document session affinity (`sessionAffinityTtlMs`) and stream idle timeout (`STREAM_IDLE_TIMEOUT_MS`) for multi-hour Codex CLI tasks, with a concrete recommended config, diagnosability string, and an explicit "defaults stay opt-in" decision — mirrored in `skills/config-codex-cli` (#7287) +- **test(dashboard):** restore dedicated regression coverage for #6815's `QuotaCardGrid` multi-column density guarantee, decoupled from the specific Tailwind token so it survives the #7027 auto-fit migration ([#7291](https://github.com/diegosouzapw/OmniRoute/pull/7291)) +- **Antivirus false-positive note** (`docs/guides/TROUBLESHOOTING.md`): documents why Avast/AVG quarantine the packaged `README.md` with `MD:HttpRequest-inf[Susp]` — a heuristic false positive on the ~15 `http://localhost:20128` examples the file ships with (via `package.json` → `files`). Covers how to stop the notifications, how to report the false positive upstream, and why the localhost examples are deliberately left alone. (#7295 — reported by @DemonNCoding, #5946) +- **chore(release):** add `scripts/release/rehome-open-prs.mjs` — the Phase 0a.0b PR re-home, scripted with a read-back after every retarget. `gh pr edit --base` exits 0 without applying (v3.8.42), `gh pr list` silently caps at 30, and the v3.8.49 freeze had 148 open PRs to move — none of which a hand-run loop survives reliably. ([#7307](https://github.com/diegosouzapw/OmniRoute/issues/7307)) +- Add an advisory production build to the PR-to-release quality workflow for non-draft code + changes and Mergify queue branches, mirroring the Node 24 Turbopack build path from full CI. +- **docs:** Add `docs/INCIDENT_RESPONSE.md` — a non-security incident-response runbook (severity ladder, first-15-minutes checklist, and per-failure-mode mitigation steps for provider outages, latency regressions, and auth/data-layer incidents) ([#7334](https://github.com/diegosouzapw/OmniRoute/pull/7334)) — thanks @KooshaPari +- **docs:** Add `docs/PERF_BUDGETS.md` — per-endpoint p50/p95/p99 latency, throughput, resource, and cold-start budget reference targets ([#7336](https://github.com/diegosouzapw/OmniRoute/pull/7336)) — thanks @KooshaPari +- **README tier-cascade diagram animated** (`docs/diagrams/tier-cascade.svg`): the ASCII 4-tier auto-fallback block in the README is now a self-contained animated SVG (SMIL-only, 16 KB, 16s loop in 4 acts — quota-out/budget-hit hand-offs down to the always-on free tier) that plays inside GitHub's `` sandbox; full flow preserved in the img alt text, hand-authored-diagrams section added to `docs/diagrams/README.md` (#7615). +- **Docs provider-count sync** (`README.md`, `AGENTS.md`, `CLAUDE.md`): provider-count mentions bumped 253 → 259 to match the auto-generated catalog, un-blocking the strict `check:docs-counts` gate that had started failing on every PR targeting the release branch (#7616). +- **README animated diagrams** (`docs/diagrams/pool-fair-share.svg`, `docs/diagrams/combo-always-on.svg`): the last two ASCII blocks in the root README — the `"team-codex"` key-pool fair-share example and the `"always-on"` priority combo — are now hand-authored SMIL SVG animations (16s loops, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe), completing the set started by tier-cascade.svg (#7615). Full block copy preserved verbatim in the `img` alt text; both registered in `docs/diagrams/README.md`. +- **docs(ops):** publish public branching/release model (`release/*` = active cycle, `main` = published line, tag = ship marker) ([#7627](https://github.com/diegosouzapw/OmniRoute/issues/7627)) — thanks @c4usal +- **README animated diagrams, round 3** (`docs/diagrams/cli-terminal.svg`, `docs/diagrams/compression-pipeline.svg`): the CLI subcommand list becomes a mini animated terminal (3 real commands typed and answered with formats copied from the actual `bin/cli` printers + a scrolling 30-subcommand ticker), and the compression flow line becomes an animated 10-engine funnel (10,000→~1,080 tok, RTK → Caveman stack highlighted, code token always preserved). SMIL-only, DESIGN_SYSTEM.md palette, GitHub ``-sandbox safe — completing the set from #7615/#7626. Both registered in `docs/diagrams/README.md`. +- README: replaced the free-tier budget preview mockup with a single detailed animated SMIL card (`docs/diagrams/free-tier-budget.svg`) — ~1.6B/mo hero, honest-math panel (15 providers ToS-flagged), 21-pool budget bar, full per-model grid, ~616M signup-credit chips, un-countable providers + $10 OpenRouter top-up, live footer (#7665) +- README: standardized all 28 tables to the same full content width — 13 tables received a calibrated invisible header spacer (`docs/screenshots/spacer.svg`), 15 already rendered full-width naturally; zero data cells changed (#7666) +- Realigned 13 test files that had drifted red on the release tip after the 102-PR merge campaign (full-suite sweep): provider counts/goldens/docs regenerated, 1M-beta assertions caught up with the live-validated behavior, and two real fixes — legacy `refresh_token` column healed before its index is created, and `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments. ([#7690](https://github.com/diegosouzapw/OmniRoute/issues/7690)) +- README: unified animated card system — numbers audited against the v3.8.49 tree (268 providers, 104 MCP tools, 25k+ tests, 26 CLIs, 40+ free-forever, 43 locales, regenerated provider reference); one flat style contract across all cards; 5 new SMIL cards (hero fused with the budget card, "Why" 10-row pain-vs-fix ledger, 18-strategy flow grid, "Private & Local-First" 11-row guarantee ledger, 3-layer resilience card replacing the always-on combo card) plus a rebuilt compact half-height CLI terminal; every animation is pause-at-t0-safe — the first frame is always the finished composition (includes the budget-bar freeze fix on the shipped free-tier card) (#7769) +- **chore(quality):** fix two release-tip base-reds blocking every fresh PR run: rename `providerTierField.ts` → `providerTierFieldApi.ts` (case-only filename collision with `ProviderTierField.tsx` from #7838 — breaks webpack on case-insensitive filesystems, caught by the #6584 guard) and register `combo-skip-conn-disable-plugin-block-7806.test.ts` (from merged #7806) in stryker `tap.testFiles`. +- **fix(i18n):** backfill the six `providers.tierOverride*` keys #7838 added to en.json into vi.json (translated with the locale's existing tier vocabulary) — their absence failed `i18n-vi-completeness` (key parity + both ICU checks) on the release tip for every fresh PR run. +- **chore(quality):** regenerate the provider translate-path golden snapshot for the navy/aihorde entries and the liquid inference URL added by #7840 — the missing regen left the golden gate (Unit shard 4/4) red on the release tip for every fresh PR run. +- **chore(quality):** prune a stale ESLint suppression for `tests/unit/db-migration-runner-account-identity.test.ts` (2 `no-explicit-any` entries that no longer occur after #7843 reorganized that test) — the leftover suppression failed `lint:json --max-warnings 0` (exit 2, "suppressions left that do not occur anymore") on the release tip for every fresh PR run. +- Extract `resolveHeadroomDetail()` from the compression-preview `dispatchCompression` dispatcher so it stays under the cognitive-complexity gate after the #8056 headroom-minRows threading (pure refactor, no behavior change). +- **chore(quality):** rebaseline complexity (2130→2183) and cognitive-complexity (951→968) across the v3.8.49 `/merge-prs` queue-drain. The first step (→2169/→956) cleared inherited base drift measured on the pristine release tip (the PR→release fast-path never ratchets these). The second step (→2183/→968) absorbs the aggregate own-growth of the 41-PR merge-train (each PR under-ceiling individually; the combined batch adds +14/+12). Owner-approved (2026-07-25); structural shrink tracked in [#3501](https://github.com/diegosouzapw/OmniRoute/issues/3501). ([#8566](https://github.com/diegosouzapw/OmniRoute/pull/8566)) — thanks @MisileLab +- **refactor(sse):** extract combo dispatch prelude (pin/fusion/pipeline/runtime-unit short-circuits) into `combo/dispatchPrelude.ts` — pure move, no behaviour change; #3501 god-file decomposition ([#8582](https://github.com/diegosouzapw/OmniRoute/pull/8582)) — thanks @MumuTW +- **chore(quality):** bank completed file-size shrinks into `file-size-baseline.json` via shrink-only `--update` on current tip (no raised caps) ([#8585](https://github.com/diegosouzapw/OmniRoute/pull/8585)) — thanks @MumuTW +- **refactor(sse):** extract combo target resolution into `combo/targetResolution.ts` (`resolveComboTargetPipeline`) — pure move, no behaviour change; #3501 PR 2 of ~7 ([#8592](https://github.com/diegosouzapw/OmniRoute/pull/8592)) — thanks @MumuTW +- **Source-scanner negative guards** (`tests/unit/source-scanner-guards.test.ts`): hard gate (no baseline, no allowlist) that fails any test variable holding project source read as text whose usages are _all_ negative guards (`assert.doesNotMatch` / `.includes(…) === false`). Those assertions pass against an empty string, so extracting the guarded code into a new file keeps them green while they protect nothing — silently deleting regression coverage during the file-splitting campaign. Classification runs on logical statements with strings, regexes, and comments blanked out, so a guard wrapped across lines cannot slip past. Fixes the 7 existing violations across 6 files with one positive anchor each; two are security scope guards that were held only by multi-line negative assertions — the SSRF guards on `/api/sync/initialize` (`providers-autosync-ssrf-323`) and the proxy-bypass guards on `chatHelpers.ts` / `chatCore.ts` (`proxy-bypass-scope-guard-3226`), the latter pinned to `handleChatCore` precisely because that file is a decomposition target. Adds `tests/_helpers/readSrc.ts`, a repo-root-relative reader that throws on a missing or empty file instead of returning `""`. Regression guards: two synthetic multi-line cases in the gate's own suite. First step of the god-file decomposition campaign tracked in #8617. ([#8619](https://github.com/diegosouzapw/OmniRoute/pull/8619)) — thanks @MumuTW +- **chore(skills):** regenerate `skills/cli-backup-sync/SKILL.md` so it matches the agent-skills catalog — drops stale `backup status` flags the generator no longer emits; unblocks Merge integrity (`check:agent-skills-sync`) for every PR against `release/v3.8.49` ([#8657](https://github.com/diegosouzapw/OmniRoute/pull/8657)) — thanks @MumuTW +- chore(quality): extract pure provider input parsers to a leaf module so the agentrouter persist test no longer drags the UI import graph (@lobehub/icons ESM build crashed Node 24's CJS require in the CI unit shard) +- Realign the Antigravity non-streaming 429-retry test with the executor's actual contract: it returns the already-converted OpenAI `chat.completion` payload, so the test asserts that payload directly instead of re-parsing it as raw SSE (which returned `null` and failed the release-tip unit suite). +- chore(quality): restore no-explicit-any severity to error (silently downgraded by #6786, broke 439 bulk suppressions), fix 2 unsuppressed anys in repro-6912 test, allowlist migration gap 121, freeze-bump stream.ts/ProxyRegistryManager/tokenHealthCheck (combined-merge drift) +- chore(base): pt-BR/en i18n keys for #6909 relay-repair/free-pool UI + align Cloud Code Gemini defaults test with the #6943 non-thinking-model contract +- chore(base): re-export relayProbeStats from localDb (db-rules gate, #6909 follow-up) and document OMNI_MAX_CONCURRENT_CONNECTIONS in .env.example/ENVIRONMENT.md (env-doc gate, #6590 follow-up) +- fix(tests): realign the disabled-compression combo integration test with the #7379 pre-dispatch context-window boundary (body resized into the 70%-threshold↔window corridor) and add an integration lock (`chatcore-context-window-boundary`) asserting over-window requests are rejected with 400 `context_length_exceeded` before any upstream fetch +- CI: `pr-test-policy` fetches the base branch with full history instead of `--depth=1` — the shallow graft made `merge-base` resolve wrong for PR branches that recently merged the release, so the three-dot diff blamed the PR for OTHER merged PRs' changes (false "deleted test"/"weakened asserts" reds; observed on #7329 being blamed for #7106's files). +- **ci:** unit fast-path sharding doubled 2→4 (halves the heaviest job's wall time) (#6781); the 3 heaviest fast-path jobs can route to the self-hosted VPS runner pool behind `USE_VPS_RUNNER` (#6691); `VPS_ALWAYS_ON` keeps the dedicated 24/7 CI host up across releases (teardown becomes a no-op) (#6693). +- **CI**: Codecov patch-coverage on every PR diff (informational during calibration — `codecov.yml` sets nothing blocking; strict-patch/lenient-project philosophy on top of the existing 60% c8 floor + ratchet); the CI coverage job now actually emits `coverage/lcov.info` (the `lcov` reporter was missing, so the artifact silently skipped it — the same file Sonar consumes) +- Classify upstream dispatches by host instead of URL path shape in the combo-routing integration harness, and close the `auto` test pool to its seeded connections. The path heuristic mislabelled every OpenAI-compatible upstream as `openai` and stopped recognising OpenAI's own `/v1/responses` calls, which made `combo-matrix/auto.test.ts` fail on a release tip whose routing was in fact correct. +- **chore(combo):** extract 8 pure error predicates and quota status helpers (`clampPercent`, `quotaRemainingPercentFromQuota`, `normalizeConnectionStatus`, `hasFutureRateLimitUntil`, `getConnectionStatusQuotaCutoffReason`, `isContextOverflow400`, `isParamValidation400`, `isModelScoped400`) from `open-sse/services/combo.ts` into `open-sse/services/combo/comboPredicates.ts` — pure move, zero behavior change; `combo.ts` shrinks from 3,651 to 3,554 lines while maintaining backward-compatible re-exports. +- **CI**: raise the Coverage job timeout 10→20min — the lcov reporter added for Codecov/Sonar (#7114) pushed the 8-shard report merge past the old cap, and three release-tip runs died at exactly 10min as job-timeout "cancelled" +- **CI**: raise the dast-smoke job timeout 12→25min — the CLI bundle build alone varies 6-11min on GitHub-hosted runners, so the old cap killed Schemathesis mid-run (3 consecutive false-negative timeouts on 2026-07-14) +- chore(validation): decompose `src/lib/providers/validation.ts` (→ 442 lines) by extracting the web-cookie, kiro and specialty inline validators into `validation/*` leaves — behavior-preserving move; the specialty validators that captured `isLocal` from the enclosing closure now take it as an explicit parameter, with the host dispatcher passing it at each call site +- chore(token-refresh): decompose `open-sse/services/tokenRefresh.ts` (999 → 724 lines) by extracting the rotation-map, CAS guard and circuit-breaker refresh logic into `tokenRefresh/*` leaves — behavior-preserving move; `tokenRefresh.ts` still re-exports the moved symbols so the public surface is unchanged +- chore(usage): decompose `open-sse/services/usage.ts` (999 → 253 lines) by extracting the crof, nanogpt, qoder, opencode, deepseek, bailian, vertex, xiaomi-mimo, xai and github usage fetchers into `usage/*` leaves — behavior-preserving move, the file is now a thin provider→fetcher dispatcher and the public import surface is unchanged +- **docs:** routing-strategy count reconciled to 18 across AUTO-COMBO.md, README and AGENTS.md, and `p2c` casing fixed to match `ROUTING_STRATEGY_VALUES` (#6643, #6644, #6646 — thanks @chirag127); CLAUDE.md updated with the renamed review/triage/implement skill-family names (#6663). +- **CI**: E2E matrix shards are now duration-balanced (LPT bin-packing over `config/quality/e2e-timings.json`) instead of Playwright's count-based `--shard` — measured skew was 14× (24m47s vs 1m47s), making E2E the CI critical path; the balancer self-verifies that every spec lands in exactly one shard and falls back to plain `--shard` on any inconsistency +- **CI**: the new Electron Windows prepare-bundle leg (WS1.5) is advisory while it matures — its first real run failed with the error swallowed by pwsh; the step now runs under bash (stderr captured) with `continue-on-error`, tracked for promotion once green +- **CI**: the Electron Package Smoke job now runs a Windows leg that executes `prepare:bundle` (the native ABI rebuild + spawn plan) per release PR — the v3.8.48 Windows bug (`npx.cmd` spawned without shell) could previously only surface on the release tag, its first-ever execution +- **Quality gates hygiene (WS6/D3 + WS1.7)**: gitleaks baseline zeroed — the 3 frozen `generic-api-key` false positives (latency field names + the public Anthropic beta-header value) are allowlisted with justification, so any NEW secret finding now regresses the ratchet from 0; the orphaned `semgrepFindings` baseline metric was dropped (never wired to a gate; CodeQL covers the OWASP families); Dockerfile now has a hadolint gate in the lint job (digest-pinned, error-threshold — the 5 pre-existing warnings stay visible without blocking) +- fix(oauth): register `ghe-copilot` in the OAuth provider id map and the client-safe MITM host mirror, which #7546 left out of both — the gap turned the whole release branch red on `oauth-providers-config` and `mitm-tool-hosts` +- fix(dashboard): add the ghe-copilot entry to the traffic-inspector agent map and type `GheConfigStep`'s `error` prop as a renderable string, clearing the two dashboard-typecheck regressions #7546 left behind +- chore(perf): add `npm run bench:heap-body` — a deterministic benchmark that attributes retained V8 heap to each request-body copy on the chat path (entry log clone, combo per-target clone, token-estimation string), reproducing the #7847 incident shape (3.05 MiB / 729 messages / 86 tools) so the clone-amplification work can be justified and regression-guarded with numbers instead of intuition +- **CI**: hotfix fast-lane — PRs labeled `hotfix` (owner-applied, production-broken only; entry policy in `docs/ops/RELEASE_CHECKLIST.md`) skip the 9-shard E2E matrix, coverage ratchet and extended gates while keeping build, unit/integration/vitest, lint/typecheck and the tarball boot-smoke (~15min instead of ~33min); tests-only diffs outside `tests/e2e/` skip the E2E matrix automatically via the new `testsOnly` change-classification output +- chore(ci): resync the stale `no-explicit-any` suppression count for `tests/unit/proxy-registry.test.ts` (frozen at 55, actual 54 since #8447) — ESLint was failing the whole run with "There are suppressions left that do not occur anymore", turning `npm run lint` red on `release/v3.8.49` for every PR branched off it +- chore(release): merge-train runs the box-tuned `test:unit` (concurrency 20) instead of two sequential 4-core CI shards (~5× faster suite) and gains an owner-approved `--fast` mode (static gates + changed tests + vitest) for intra-day mega-train drains +- **chore(release):** merge-train `--fast` now classifies changed tests with the same + `tests/unit/{…}` subdir allowlist `test:unit` runs — vitest-only subdirs (e.g. + `tests/unit/autoCombo/`) are skipped instead of misrun under node:test, and + `tests/unit/ui/**/*.test.ts` (node:test) is no longer over-excluded. +- **CI**: quality.yml draft guards now also match Mergify speculative merge-queue PRs (`mergify/merge-queue/*` heads are drafts by design) — without this every queued batch failed its anchor check in 2s and dequeued +- **Merge queue (D5)**: reviewed PRs now merge through the Mergify queue (`.mergify.yml`, Open Source plan) — entry is the owner-applied `queue` label AFTER the pre-merge ⭐ gate; batches of up to 10 validate together with automatic bisection of red batches (~log2(N) instead of N revalidations); the manual merge-train is codified as the fallback runbook in `docs/ops/MERGE_TRAIN.md` with the freeze/cross-session guardrails +- **Release**: npm publishing is now STAGED by default — the workflow boots the packed tarball (`check:pack-boot`) and runs `npm stage publish` (bytes parked on the registry, not installable); the owner verifies the staged bytes and releases them with `npm stage approve` + 2FA, moving the human gate to after the proof (the structural fix for the #7065 broken-tarball class); `publish_mode=direct` remains as a documented emergency fallback +- chore(release): v3.8.47 pre-flight — relocate #6943 orphan test to a collected path, restore no-explicit-any suppression match, testFrozen bump translator-openai-to-gemini (1541→1553), zizmor rebaseline 159→169 +- **Docs**: `QUALITY_GATES.md` now codifies the per-runner test retry policy (Playwright 1 CI retry with trace; Vitest per-test explicit quarantine only; node:test never) with target flake SLOs, and the release-level ratchet-drift rule (combination drift on the pure tip is the release captain's to fix once on the branch — never pushed onto contributor PRs, never rebaselined per-PR) +- chore(quality): owner-approved ratchet rebaseline for the v3.8.49 merge campaign — complexity 2072→2130, cognitive-complexity 900→950 (the day's 17 merged PRs consumed the entire slack; wide margin chosen over per-PR extraction for the rest of the cycle) +- **docs(readme):** fix stale counts — 18 routing strategies (adds the missing `pipeline` row), 94 MCP tools, 12-factor Auto-Combo scoring. +- Rebaseline the cyclomatic-complexity ceiling (2059 → 2072) and cognitive-complexity ceiling (890 → 900) to absorb a cluster of clean contributor feature PRs whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit slack. Owner-approved; structural shrink remains tracked in #3501. +- **CI**: release-green validation is now continuous — every code push to `release/v*` (including the captain's direct sync-back pushes, the one previously ungated write path) triggers a `--quick` HARD-gate run with per-branch superseded-run cancellation, and the tracking issue names the offending push range; the deep `--with-build --full-ci` sweep now runs 3×/day instead of nightly-only (base-red MTTD: ≤24h → ~15min after the offending push) +- **chore(ci):** fix two shared base-reds on the release tip that blocked the PR queue — register `cliproxyapi-model-mapping-dispatch.test.ts` in `stryker.conf.json` `tap.testFiles` (mutation-coverage gap left by #6903) and update `provider-models-route-codex.test.ts` to expect Codex client version `0.144.0` (stale assertion left by #6780's production bump). +- **docs:** refresh `llm.txt` to the current project state (248 providers, 94 MCP tools / 30 scopes, 18 routing strategies, 12-factor Auto-Combo scoring, v3.8.47) and sync its 42 i18n mirrors; move the implemented design-system plan from the repo root to `docs/architecture/DESIGN_SYSTEM.md` rewritten as a reference doc. +- Strengthen the `compareRouterEvalRuns` regression test to assert the actual AIQ and cost regression reasons instead of counting entries, clearing the weakened-assert (test-masking) gate on the release tip. +- **Ops**: `scripts/ops/runner-janitor.sh` + `docs/ops/RUNNER_BOX.md` codify the self-hosted runner box hygiene that was manual discipline — 30min cron sweeping stale runner temp dirs, alerting at ≥85% disk, and enforcing the proven 4-runner ceiling on the 16 GB box (8-wide OOM-killed jobs twice on the v3.8.47 release day) +- **chore(security):** scrub hardcoded live-instance credentials (API key + auth cookie + host URL) from the `tests/boundary/*.live.test.ts` files landed via #6786 — they now read `OMNIROUTE_TEST_BASE` / `OMNIROUTE_TEST_BEARER` / `OMNIROUTE_TEST_COOKIE` from the environment and stay gated behind `RUN_BOUNDARY_LIVE=1`. +- **Tests**: the #6634 self-reference test now fetches `origin/main` on demand and skips cleanly when the ref is unreachable — it failed as a false positive on shallow/single-ref checkouts (GitHub-hosted runners) +- Register 5 covering unit tests (account-fallback lockout eviction, cliproxyapi dedicated credential #7645, combo least-used account, combo recovery-hint, route-guard forge/jcode local-only) in `stryker.conf.json` `tap.testFiles` to clear the release base-red. +- chore(quality): register microsoft-designer-web-6672 test in stryker tap.testFiles (unblocks Fast Quality Gates base-red) +- **Release tooling**: `sync-next-cycle.mjs` now runs `validate-release-green --quick` on the merged tree BEFORE pushing the parallel-cycle sync-back — the one write path to the release branch that had no CI gate; a red merged tree stays local instead of turning the whole PR queue red (`--skip-green-gate` is the documented emergency hatch) +- Rebaseline `testFrozen` for `tests/unit/providers-page-utils.test.ts` (1107 → 1294) after #7775 legitimately grew it with the Kimi provider pinning + supporter-card coverage; the merged PR did not update the baseline, leaving the `test-file-size` gate red on the release tip. +- **chore(quality):** tighten the coverage ratchet to the CI's real numbers (branches 73→78.1, statements/lines 76.5→80.8, functions 82→86.44, plus 7 per-module floors). The gate had been asking for this in plain text; the values come from the merged-coverage run on `main`, not a local run (local measures ~68% vs CI's ~80% — the baseline's own note warns about that gap). +- **chore(quality):** split `open-sse/services/tokenRefresh.ts` (2249 lines, frozen) into per-provider leaves — `open-sse/services/tokenRefresh/providers/{windsurf,codebuddyCn,cline,kimiCoding,gitlabDuo,claudeOAuth,google,codex,kiro,qoder,github,copilot}.ts` plus a `tokenRefresh/shared.ts` for the cross-provider OAuth-error classifier and form-body helper — pure move, zero behavior change; the file shrinks to ~989 lines and every previously-public export (`refreshCopilotToken`, `getAccessToken`, `extractOAuthErrorCode`, etc.) is re-exported unchanged so no importer needed to change. Idea originally proposed by @KooshaPari in #7338 against a much older base; redone here against the current tip. +- chore(quality): re-pin the file-size ceilings touched by the v3.8.49 merge-train 1H (31 PRs) and register three covering tests that had drifted out of `stryker.conf.json` — the mutation gate was failing `Fast Quality Gates` on every new PR +- chore(quality): re-pin the `chatCore.ts` file-size ceiling for the Responses multi-turn image compaction added in #8595 +- chore(quality): align the pack-artifact expected-path fixture with the Android/Termux cache module added in #8593, and re-pin the `chatCore.ts` ceiling grown by the merge-train 2 batch +- chore(quality): re-pin the `apiKeys.ts` and `chatCore.ts` ceilings grown by the merge-train 3 batch, and register the Cloudflare-1010 regression test in `stryker.conf.json` +- **CI**: Playwright E2E and both vitest suites now emit JUnit and upload to Trunk Flaky Tests (org `omniroute`) — advisory step, own-origin only, uploader action SHA-pinned (WS5.2/5.3 of the quality plan; node:test stays out of the first wave) +- **CI**: the fast-path Vitest job (every PR) now also emits JUnit and uploads to Trunk Flaky Tests — the heavy-gate uploads alone (release PR only) would never accumulate flaky-detection volume +- **CI**: TypeScript 7 (native compiler, GA 2026-07-08) now runs as an advisory SHADOW of the blocking `typecheck:core` gate on the fast path — same tsconfig, isolated `npx` (no dependency change; the Compiler API only lands in TS 7.1, so typescript-eslint/type-coverage/Stryker stay on 6.x). Local parity proven (0 errors on both, exit 0); promotion to the blocking gate after ~1 week of CI parity +- **maintenance(quality):** clear v3.8.49 owner-PR-campaign base-reds on `release/v3.8.49` (accumulated because fast-gates PR→release skip the complexity/golden/file-size ratchets, surfaced only on re-sync): regenerate the `provider/translate-path` golden snapshot for the new providers; re-point the `#6772` connId-prefix test off the now-reserved `fta` alias (claimed by freetheai #7602 — built-in aliases shadow custom-node prefixes by design); bump the complexity baseline 2056→2058 for the new provider dispatch handlers. No behavior change. +- **Release tooling**: new `scripts/release/verify-published.mjs ` — post-publish net that installs the published version from the public registry inside a clean `node:24-slim` container and boots it until `/api/monitoring/health` reports the expected version (validates the exact bytes users install, on a machine with no repo/devbox state); wired into the release Phase 4 monitoring playbook +- **CI**: promote `test:vitest:ui` to a blocking gate — the suite is 870/870 green again after the WS6.1 triage (#7127), so `continue-on-error` is removed from the vitest job +- chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) + + + +### 🙌 Contributors + +Thanks to everyone whose work landed in v3.8.49: + +| Contributor | PRs / Issues | +| --- | --- | +| [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | +| [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | +| [@advane204f](https://github.com/advane204f) | direct commit / report | +| [@Ajeesh25353646](https://github.com/Ajeesh25353646) | #7528 | +| [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814 | +| [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | +| [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | +| [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | +| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | +| [@anhdiepmmk](https://github.com/anhdiepmmk) | direct commit / report | +| [@anndev-69](https://github.com/anndev-69) | direct commit / report | +| [@apoapostolov](https://github.com/apoapostolov) | #8127 | +| [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006 | +| [@Arul-](https://github.com/Arul-) | #7878 | +| [@asynx6](https://github.com/asynx6) | direct commit / report | +| [@attid](https://github.com/attid) | #6984 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@beingshafin](https://github.com/beingshafin) | direct commit / report | +| [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@c4usal](https://github.com/c4usal) | #7627, #8129 | +| [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | +| [@Capslockb](https://github.com/Capslockb) | #7892 | +| [@CarmeloCampos](https://github.com/CarmeloCampos) | direct commit / report | +| [@Chewji9875](https://github.com/Chewji9875) | #7545 | +| [@chirag127](https://github.com/chirag127) | #6022, #6593, #6643, #6644, #6646, #6650, #6769, #6771, #6804, #7079, #7520, #8143 | +| [@chitholian](https://github.com/chitholian) | direct commit / report | +| [@chy1211](https://github.com/chy1211) | direct commit / report | +| [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | +| [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | +| [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | +| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@dionisius95](https://github.com/dionisius95) | direct commit / report | +| [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | +| [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | +| [@epsilonode](https://github.com/epsilonode) | #8724 | +| [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | +| [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | +| [@felipeleite](https://github.com/felipeleite) | direct commit / report | +| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@FenjuFu](https://github.com/FenjuFu) | #7942 | +| [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | +| [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | +| [@gitcommit90](https://github.com/gitcommit90) | #6986 | +| [@glazec](https://github.com/glazec) | #8632 | +| [@growab](https://github.com/growab) | #7062 | +| [@guanbear](https://github.com/guanbear) | #7028 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@HassiyYT](https://github.com/HassiyYT) | #7864 | +| [@heishen6](https://github.com/heishen6) | direct commit / report | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845 | +| [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | +| [@huohua-dev](https://github.com/huohua-dev) | #6794 | +| [@hydraxman](https://github.com/hydraxman) | #7909 | +| [@iamraydoan](https://github.com/iamraydoan) | #6798 | +| [@ianriizky](https://github.com/ianriizky) | #6072, #6538 | +| [@ikelvingo](https://github.com/ikelvingo) | #8355 | +| [@insoln](https://github.com/insoln) | #7906, #7908, #8041, #8054, #8062 | +| [@irvandikky](https://github.com/irvandikky) | #7695 | +| [@isiahw1](https://github.com/isiahw1) | #7555 | +| [@itiwant](https://github.com/itiwant) | direct commit / report | +| [@janeza2](https://github.com/janeza2) | #6308 | +| [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | +| [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | +| [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | +| [@KaynXu](https://github.com/KaynXu) | #8284 | +| [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | +| [@KunN-21](https://github.com/KunN-21) | direct commit / report | +| [@leninejunior](https://github.com/leninejunior) | #8049 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | +| [@loulanyue](https://github.com/loulanyue) | #7540 | +| [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | +| [@lunkerchen](https://github.com/lunkerchen) | #8024 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@megamen32](https://github.com/megamen32) | #7313 | +| [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@MikeTuev](https://github.com/MikeTuev) | #6586 | +| [@mikolaj92](https://github.com/mikolaj92) | #6973 | +| [@MisileLab](https://github.com/MisileLab) | #8566 | +| [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | +| [@mrprohack](https://github.com/mrprohack) | direct commit / report | +| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | +| [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | +| [@not-knope](https://github.com/not-knope) | #8206 | +| [@nramabad](https://github.com/nramabad) | #7926 | +| [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | +| [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | +| [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@QRcode1337](https://github.com/QRcode1337) | #7034 | +| [@quanturbo](https://github.com/quanturbo) | #6780 | +| [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@ricatix](https://github.com/ricatix) | direct commit / report | +| [@ridho9](https://github.com/ridho9) | #8310 | +| [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | +| [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | +| [@rushsinging](https://github.com/rushsinging) | #7256 | +| [@ryanngit](https://github.com/ryanngit) | direct commit / report | +| [@samir-abis](https://github.com/samir-abis) | direct commit / report | +| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | +| [@Securiteru](https://github.com/Securiteru) | #7683 | +| [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@SingCJ](https://github.com/SingCJ) | direct commit / report | +| [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | +| [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | +| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | +| [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | +| [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | +| [@tianrking](https://github.com/tianrking) | #7353 | +| [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | +| [@TitoTFP](https://github.com/TitoTFP) | #8838 | +| [@tjengbudi](https://github.com/tjengbudi) | #4009 | +| [@tmone](https://github.com/tmone) | #7806, #7933 | +| [@TrackCrewGalore](https://github.com/TrackCrewGalore) | #6271, #8128 | +| [@trfi](https://github.com/trfi) | direct commit / report | +| [@TuyulSpam](https://github.com/TuyulSpam) | direct commit / report | +| [@ViFigueiredo](https://github.com/ViFigueiredo) | #7301 | +| [@vzts](https://github.com/vzts) | #7390 | +| [@warelik](https://github.com/warelik) | direct commit / report | +| [@way-art](https://github.com/way-art) | direct commit / report | +| [@webmasterarbez](https://github.com/webmasterarbez) | #7504 | +| [@wgordon17](https://github.com/wgordon17) | #8852 | +| [@whale9820](https://github.com/whale9820) | direct commit / report | +| [@Wibias](https://github.com/Wibias) | #7125 | +| [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | +| [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | +| [@XCrag](https://github.com/XCrag) | direct commit / report | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | +| [@xxue-z](https://github.com/xxue-z) | #7098 | +| [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | +| [@yidecode](https://github.com/yidecode) | direct commit / report | +| [@yinaoxiong](https://github.com/yinaoxiong) | #6805 | +| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer | + --- ## [3.8.48] — 2026-07-13