Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 0 additions & 21 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,13 @@
- **feat(usage):** add on-demand period-scoped usage-data reset (Settings → System Storage) with a purge API and time-window selector.
- **feat(claude-code):** add an opt-in auto-permission classifier compat mode (off/auto/always) for Claude Code, toggleable from the CLI Code settings.
- **feat(providers):** add optional client-identity header profiles for compatible nodes — preset User-Agent/fingerprint headers (e.g. matching a known CLI) merged into the existing customHeaders field.
- **feat(xai):** surface Grok usage on the quota dashboard via local usage-history aggregation. (thanks @DevEstacion)
- **feat(services):** add **Mux** (`coder/mux`) as a managed embedded service — install/start/stop/restart/logs lifecycle + dashboard tab, loopback-only API, `127.0.0.1`-bound with the auth token passed via env (never argv). Ported from upstream 9router#1802. (thanks @Ansh7473)
- **feat(services):** promote **Bifrost** (`@maximhq/bifrost`) to a supervised embedded service ([#5670](https://github.com/diegosouzapw/OmniRoute/issues/5670)) — full install/start/stop/restart/update/status/auto-start lifecycle + dashboard tab, loopback-only API (hard rule #17). When a supervised Bifrost is running and `BIFROST_BASE_URL` is unset, the relay route auto-selects it as the routing backend (`getBifrostRoutingConfig()`); an explicit `BIFROST_BASE_URL` always takes precedence.
- **feat(proxy):** proxy-registry batch management ([#5918](https://github.com/diegosouzapw/OmniRoute/pull/5918)) — `POST /api/settings/proxies/batch-delete` (delete many proxies in one request) and `POST /api/settings/proxies/auto-test` (reachability-test proxies with optional auto-remove of dead ones), plus a background health scheduler (`src/lib/proxyHealth/scheduler.ts`) that periodically probes registered proxies and can auto-remove persistently-dead ones. Configurable via `PROXY_HEALTH_ENABLED` / `PROXY_HEALTH_INTERVAL_MS` / `PROXY_HEALTH_TEST_URL` / `PROXY_AUTO_REMOVE` / `PROXY_AUTO_REMOVE_AFTER` (the probe target is now operator-configurable instead of a hardcoded endpoint). Dashboard gains batch-select checkboxes, a "Test All" action, and colored proxy health indicators. Regression guard: `tests/unit/proxy-batch-routes-5918.test.ts`. (thanks @oyi77)

### 🔧 Bug Fixes

- **providers (alias resolution followed only one hop):** `resolveProviderAlias()` did a single-hop lookup, so a genuine two-hop alias chain (`oc` → `opencode` → `opencode-zen`, where the parent OpenCode provider registers `alias: "oc"` and a manual override maps `opencode` → the `opencode-zen` free tier) resolved `oc/<model>` to the intermediate `opencode` instead of the final provider. Resolution now follows the chain transitively, guarded by both a depth limit and a seen-set so cycles can't loop. Regression guard: `tests/unit/provider-alias-transitive-5918.test.ts`. ([#5918](https://github.com/diegosouzapw/OmniRoute/pull/5918) — thanks @oyi77)

- fix(providers): strip orphan tool_result blocks on the Antigravity MITM path before forwarding to Claude ([#6026](https://github.com/diegosouzapw/OmniRoute/issues/6026))

- **dashboard ("Update now" → Internal Server Error):** clicking **Update now** on the dashboard home could crash the page with a blank "Internal Server Error" screen (`Minified React error #31`). The handler POSTs the loopback-only `/api/system/version` auto-update endpoint and, on a non-OK JSON response (e.g. a `403` when the dashboard is reached through a reverse proxy / non-loopback origin), passed the raw error envelope object `{ error: { code, message, correlation_id } }` straight to `notify.error()`, which rendered the object as a React child and threw #31. The update-error path now funnels the body through `extractApiErrorMessage()` (the same safe extractor added in #5340), so a readable string always reaches the toast. Regression guard: `tests/unit/ui/home-update-error-render-5991.test.ts`. ([#5991](https://github.com/diegosouzapw/OmniRoute/issues/5991))

- **kiro (system prompt leaked as raw user text):** when Claude Code routed through the Kiro/CodeWhisperer backend, the `system` message was normalized to a `user` turn with no wrapper, so the entire system prompt (environment info, tool definitions, memory instructions, etc.) appeared as if the user had typed it — polluting the model context. System-origin content is now wrapped in `<system-reminder>` tags before being merged into the Kiro user message, so the model can distinguish it from real user input. Real user turns are untouched. Regression guard: `tests/unit/kiro-system-reminder-2306.test.ts`. (thanks @VitzS7)

- **antigravity/gemini tool calls (`400 Unknown name "multipleOf"`):** requests routed to antigravity/gemini models with tools that declare a `multipleOf` numeric constraint failed with a hard upstream `400` (`Invalid JSON payload received. Unknown name "multipleOf"`). `multipleOf` is not part of the Gemini/antigravity OpenAPI 3.0 schema subset and was not being stripped from `function_declarations`. It is now removed at every schema level (top-level, nested, and array `items`), alongside the other unsupported constraints; `minimum`/`maximum` remain untouched. Regression guard: `tests/unit/gemini-multipleof-2309.test.ts`. (thanks @abil0321)

- **cline (empty/false-502 non-streaming responses):** the Cline gateway can wrap OpenAI-compatible chat completions in a `{ success, data: { choices, usage, … } }` envelope. The non-streaming path checked the top-level body for empty content before unwrapping, so a valid Cline response was treated as malformed. The body is now unwrapped via `unwrapClineNonStreamingEnvelope()` right after the provider-envelope unwrap and before the empty-content check, closing the remaining gap from #5956/#5924. Regression guard: `tests/unit/cline-response-envelope.test.ts`. ([#5956](https://github.com/diegosouzapw/OmniRoute/issues/5956) — thanks @KooshaPari)

- **combo (per-model-quota providers exhausted on a single model 500):** for per-model-quota providers (gemini, github, passthrough, compatible) that multiplex many models behind one connection, a model-level `500` (e.g. Gemini "Internal error encountered") wrongly marked the whole connection exhausted, so sibling models on the same connection were skipped and the combo could 502 instead of falling back. `markConnectionLevelExhaustion` now leaves the connection eligible on a `500` for per-model-quota providers (other connection-level statuses — 408/502/503/504/524 — still exhaust correctly), and the retry loop early-returns when a model is already in lockout. Regression guard: `tests/unit/combo/combo-target-exhaustion.test.ts`. ([#5976](https://github.com/diegosouzapw/OmniRoute/pull/5976) — thanks @hartmark)

- fix(providers): GitLab Duo executor now emulates OpenAI tool_calls (#6051)

- **grok-cli (context-aware routing filtered out larger requests):** the `grok-cli` registry declared a 128k `contextLength` for `grok-build` and `grok-composer-2.5-fast`, below their real Grok CLI capacities, so OmniRoute's context-aware routing dropped these models for larger prompts. Updated to match the actual `/context` values — `grok-build` → 256000 (xAI-published 256k window) and `grok-composer-2.5-fast` → 200000. Registry-only; no runtime logic change. ([#5913](https://github.com/diegosouzapw/OmniRoute/pull/5913) — thanks @Chewji9875)

### 📝 Maintenance

- **ci (env-doc base-red):** document `BIFROST_PORT` in `.env.example` + `docs/reference/ENVIRONMENT.md`. The Bifrost embedded-service merge referenced `process.env.BIFROST_PORT` (`src/lib/services/bootstrap.ts`, default `8080`) without documenting it, so `check:env-doc-sync` failed on the release tip — reddening the `Fast Quality Gates` job for **every** open PR→release regardless of its content. Docs-only; no runtime change.
- **test (deflake `setup-claude`):** `tests/unit/cli/setup-claude.test.ts` failed ~50% of runs with `Unable to deserialize cloned data due to invalid or unsupported version` at file teardown (all subtests passed), randomly reddening `Unit Tests fast-path (2/2)` / `Fast Quality Gates` across the PR→release queue. Root cause: `node --test` streams each file's report to the parent as V8-serialized frames on fd 1 (stdout), and the CLI helper under test (`syncClaudeProfilesFromModels`) prints progress via `console.log` — that stdout output interleaved with the serialized frames and corrupted the stream. The test now silences the stdout-writing `console` methods for the file's duration (no assertion inspects stdout), making it deterministic (15/15 green locally). ([#5959](https://github.com/diegosouzapw/OmniRoute/issues/5959))

- **API validation:** add a `validatedJsonBody(request, schema)` helper in `src/shared/validation/helpers.ts` that fuses JSON body parsing and Zod validation into a single call, returning either the type-narrowed data or a ready-to-return 400 `NextResponse` with the standard error envelope. Salvaged from the closed refactor PR #5075 (Tier 1 portable helper) with a focused 6-case regression test. Co-authored-by: KooshaPari <KooshaPari@users.noreply.github.com>
Expand Down
Loading