diff --git a/CHANGELOG.md b/CHANGELOG.md
index 912fe2ca683d..c5ae417412a1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,25 @@
## [Unreleased]
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated β Next.js middleware matcher omitted `/home`, so any visit reached the page directly on `REQUIRE_LOGIN` deployments (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 β extract no-log state to `compliance/noLog.ts`, switch callers to the leaf module, keep `compliance/index.ts` re-exports for backwards compat (#2650)
+- **deepseek:** guard PoW solver Web Worker handler so `require()` no longer throws `ReferenceError: onmessage is not defined` under Node strict mode (#2724)
+- **combos:** include no-auth providers (FreeAIAPIKey, BluesMinds, FreeModel.dev, opencode, β¦) in the combo builder picker β they were invisible because they never get rows in `provider_connections` (#2737)
+- **translator:** allow the `web_search` server-tool family (`web_search_20250305`, `web_search_20250101`, plain `web_search`) in the Responses API translator and preserve the original versioned name on output (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow so the Trae IDE no longer 500s during token import (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace so aliases set via the Settings UI (e.g. `gpt-5.4 β cx/gpt-5.4`) are honored instead of being overridden by provider inference (#2618, #2208)
+- **kiro:** fall back to `document.execCommand("copy")` when the Clipboard API is unavailable (HTTP/non-secure contexts), so the "Copy authorization link" button works on LAN deployments (#2689)
+- **cli:** raise `omniroute serve` ready timeout from 20s to 60s and add a TCP-listening fallback so Windows users no longer get phantom timeouts during slow Next.js cold start (#2460)
+
+## [Unreleased]
+
### β¨ New Features
- **proxy:** serverless relay endpoints with rate limiting (#2734)
diff --git a/bin/cli/commands/serve.mjs b/bin/cli/commands/serve.mjs
index 17b58e30c6b4..24fa344d4a89 100644
--- a/bin/cli/commands/serve.mjs
+++ b/bin/cli/commands/serve.mjs
@@ -269,7 +269,7 @@ async function runWithSupervisor(
});
if (!showLog) {
- waitForServer(dashboardPort, 20000).then(async (up) => {
+ waitForServer(dashboardPort, 60000).then(async (up) => {
if (up) {
if (useTray) await maybeStartTray(dashboardPort, apiPort, supervisor);
onReady(dashboardPort, apiPort, noOpen);
diff --git a/bin/cli/utils/pid.mjs b/bin/cli/utils/pid.mjs
index 1f3ff526dfe6..6c94437e372b 100644
--- a/bin/cli/utils/pid.mjs
+++ b/bin/cli/utils/pid.mjs
@@ -61,16 +61,50 @@ export function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
-export async function waitForServer(port, timeout = 15000) {
+// #2460: Default raised from 15s to 60s so Windows users (slower Next.js
+// cold start due to filesystem watchers, antivirus, etc.) get a working
+// "server ready" signal instead of a phantom timeout while the server is
+// still booting. TCP fallback marks the server as ready when the port
+// has been listening for >= 3s consecutively but /api/monitoring/health
+// has not yet been mounted β common during dev cold start.
+export async function waitForServer(port, timeout = 60000) {
const start = Date.now();
+ let tcpListeningSince = null;
while (Date.now() - start < timeout) {
try {
const res = await fetch(`http://localhost:${port}/api/monitoring/health`, {
signal: AbortSignal.timeout(2000),
});
if (res.ok) return true;
- } catch {}
+ // Server responded but health endpoint is not ready yet β keep
+ // polling, but the fact that we got a response means TCP is open.
+ if (tcpListeningSince === null) tcpListeningSince = Date.now();
+ } catch {
+ const listening = await isPortListening(port).catch(() => false);
+ if (listening) {
+ if (tcpListeningSince === null) tcpListeningSince = Date.now();
+ if (Date.now() - tcpListeningSince >= 3000) return true;
+ } else {
+ tcpListeningSince = null;
+ }
+ }
await sleep(500);
}
return false;
}
+
+async function isPortListening(port) {
+ const net = await import("node:net");
+ return new Promise((resolve) => {
+ const socket = net.connect({ host: "127.0.0.1", port, timeout: 1000 });
+ const finish = (ok) => {
+ try {
+ socket.destroy();
+ } catch {}
+ resolve(ok);
+ };
+ socket.once("connect", () => finish(true));
+ socket.once("error", () => finish(false));
+ socket.once("timeout", () => finish(false));
+ });
+}
diff --git a/docs/i18n/ar/CHANGELOG.md b/docs/i18n/ar/CHANGELOG.md
index e4ec1f60e2c7..93d35e90a534 100644
--- a/docs/i18n/ar/CHANGELOG.md
+++ b/docs/i18n/ar/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/az/CHANGELOG.md b/docs/i18n/az/CHANGELOG.md
index 61abf8c13885..55977e916b1a 100644
--- a/docs/i18n/az/CHANGELOG.md
+++ b/docs/i18n/az/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/bg/CHANGELOG.md b/docs/i18n/bg/CHANGELOG.md
index 61abf8c13885..55977e916b1a 100644
--- a/docs/i18n/bg/CHANGELOG.md
+++ b/docs/i18n/bg/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/bn/CHANGELOG.md b/docs/i18n/bn/CHANGELOG.md
index e6870e5f08f2..c0b7d896f3c9 100644
--- a/docs/i18n/bn/CHANGELOG.md
+++ b/docs/i18n/bn/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/cs/CHANGELOG.md b/docs/i18n/cs/CHANGELOG.md
index 78452adfcd92..e85189339f96 100644
--- a/docs/i18n/cs/CHANGELOG.md
+++ b/docs/i18n/cs/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/da/CHANGELOG.md b/docs/i18n/da/CHANGELOG.md
index 5ddaf0f8f3db..9118f5b7525a 100644
--- a/docs/i18n/da/CHANGELOG.md
+++ b/docs/i18n/da/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/de/CHANGELOG.md b/docs/i18n/de/CHANGELOG.md
index a786a8db71e5..709596b56ea0 100644
--- a/docs/i18n/de/CHANGELOG.md
+++ b/docs/i18n/de/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/es/CHANGELOG.md b/docs/i18n/es/CHANGELOG.md
index fdc84441d636..b6d833255daf 100644
--- a/docs/i18n/es/CHANGELOG.md
+++ b/docs/i18n/es/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/fa/CHANGELOG.md b/docs/i18n/fa/CHANGELOG.md
index fce3d9a86895..db1752c50fb6 100644
--- a/docs/i18n/fa/CHANGELOG.md
+++ b/docs/i18n/fa/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/fi/CHANGELOG.md b/docs/i18n/fi/CHANGELOG.md
index 33b83a670df4..6457b9b5722f 100644
--- a/docs/i18n/fi/CHANGELOG.md
+++ b/docs/i18n/fi/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/fr/CHANGELOG.md b/docs/i18n/fr/CHANGELOG.md
index d25e573e994c..7a5403714574 100644
--- a/docs/i18n/fr/CHANGELOG.md
+++ b/docs/i18n/fr/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/gu/CHANGELOG.md b/docs/i18n/gu/CHANGELOG.md
index 173e35de5fca..ed2baef172c0 100644
--- a/docs/i18n/gu/CHANGELOG.md
+++ b/docs/i18n/gu/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/he/CHANGELOG.md b/docs/i18n/he/CHANGELOG.md
index 14eba4f2ae72..cbe80b59d3e5 100644
--- a/docs/i18n/he/CHANGELOG.md
+++ b/docs/i18n/he/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/hi/CHANGELOG.md b/docs/i18n/hi/CHANGELOG.md
index bfa8ad68f6f3..0e23ef0a986c 100644
--- a/docs/i18n/hi/CHANGELOG.md
+++ b/docs/i18n/hi/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/hu/CHANGELOG.md b/docs/i18n/hu/CHANGELOG.md
index c0bc76b1a38e..2d6297764945 100644
--- a/docs/i18n/hu/CHANGELOG.md
+++ b/docs/i18n/hu/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/id/CHANGELOG.md b/docs/i18n/id/CHANGELOG.md
index b41fd38e06e4..3d7bf9aeb28a 100644
--- a/docs/i18n/id/CHANGELOG.md
+++ b/docs/i18n/id/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/in/CHANGELOG.md b/docs/i18n/in/CHANGELOG.md
index 8eb8afa0d5ed..836886b526d7 100644
--- a/docs/i18n/in/CHANGELOG.md
+++ b/docs/i18n/in/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/it/CHANGELOG.md b/docs/i18n/it/CHANGELOG.md
index 000c080ffa50..e6a92b4934e8 100644
--- a/docs/i18n/it/CHANGELOG.md
+++ b/docs/i18n/it/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/ja/CHANGELOG.md b/docs/i18n/ja/CHANGELOG.md
index c3e153579ac0..1efa867771a0 100644
--- a/docs/i18n/ja/CHANGELOG.md
+++ b/docs/i18n/ja/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/ko/CHANGELOG.md b/docs/i18n/ko/CHANGELOG.md
index c2dd0705fc50..404c0bf9261e 100644
--- a/docs/i18n/ko/CHANGELOG.md
+++ b/docs/i18n/ko/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/mr/CHANGELOG.md b/docs/i18n/mr/CHANGELOG.md
index 84d6728bbbb7..96074e285cb0 100644
--- a/docs/i18n/mr/CHANGELOG.md
+++ b/docs/i18n/mr/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/ms/CHANGELOG.md b/docs/i18n/ms/CHANGELOG.md
index 4e4818db7261..4e8546938492 100644
--- a/docs/i18n/ms/CHANGELOG.md
+++ b/docs/i18n/ms/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/nl/CHANGELOG.md b/docs/i18n/nl/CHANGELOG.md
index 430c806ccda3..85e15ce194f9 100644
--- a/docs/i18n/nl/CHANGELOG.md
+++ b/docs/i18n/nl/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/no/CHANGELOG.md b/docs/i18n/no/CHANGELOG.md
index e0d186dd1f5d..eaa8d08d99e6 100644
--- a/docs/i18n/no/CHANGELOG.md
+++ b/docs/i18n/no/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/phi/CHANGELOG.md b/docs/i18n/phi/CHANGELOG.md
index 07c38a325318..4f51106d343d 100644
--- a/docs/i18n/phi/CHANGELOG.md
+++ b/docs/i18n/phi/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/pl/CHANGELOG.md b/docs/i18n/pl/CHANGELOG.md
index fda50f7d95d4..249aed3ddbf2 100644
--- a/docs/i18n/pl/CHANGELOG.md
+++ b/docs/i18n/pl/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/pt-BR/CHANGELOG.md b/docs/i18n/pt-BR/CHANGELOG.md
index 6a0c886c7a89..73db08997212 100644
--- a/docs/i18n/pt-BR/CHANGELOG.md
+++ b/docs/i18n/pt-BR/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/pt/CHANGELOG.md b/docs/i18n/pt/CHANGELOG.md
index c182f3c7ecd5..56cd6b40e831 100644
--- a/docs/i18n/pt/CHANGELOG.md
+++ b/docs/i18n/pt/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/ro/CHANGELOG.md b/docs/i18n/ro/CHANGELOG.md
index 2ea2c6e1a19d..6e233b659f54 100644
--- a/docs/i18n/ro/CHANGELOG.md
+++ b/docs/i18n/ro/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/ru/CHANGELOG.md b/docs/i18n/ru/CHANGELOG.md
index 2dadc9d6babb..733c391b887a 100644
--- a/docs/i18n/ru/CHANGELOG.md
+++ b/docs/i18n/ru/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/sk/CHANGELOG.md b/docs/i18n/sk/CHANGELOG.md
index 22e8618918fc..f1ef4f182068 100644
--- a/docs/i18n/sk/CHANGELOG.md
+++ b/docs/i18n/sk/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/sv/CHANGELOG.md b/docs/i18n/sv/CHANGELOG.md
index ac1b9ab37efd..0911fe1cace2 100644
--- a/docs/i18n/sv/CHANGELOG.md
+++ b/docs/i18n/sv/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/sw/CHANGELOG.md b/docs/i18n/sw/CHANGELOG.md
index 4e06d1be6ab1..8fc40c668de4 100644
--- a/docs/i18n/sw/CHANGELOG.md
+++ b/docs/i18n/sw/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/ta/CHANGELOG.md b/docs/i18n/ta/CHANGELOG.md
index 710f8ed939fe..966f4bfc7210 100644
--- a/docs/i18n/ta/CHANGELOG.md
+++ b/docs/i18n/ta/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/te/CHANGELOG.md b/docs/i18n/te/CHANGELOG.md
index 9ff6b41223c4..15ba2858cc24 100644
--- a/docs/i18n/te/CHANGELOG.md
+++ b/docs/i18n/te/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/th/CHANGELOG.md b/docs/i18n/th/CHANGELOG.md
index e37988d07b44..6b39c9364931 100644
--- a/docs/i18n/th/CHANGELOG.md
+++ b/docs/i18n/th/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/tr/CHANGELOG.md b/docs/i18n/tr/CHANGELOG.md
index f86f6ad2a5d6..c261e947feea 100644
--- a/docs/i18n/tr/CHANGELOG.md
+++ b/docs/i18n/tr/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/uk-UA/CHANGELOG.md b/docs/i18n/uk-UA/CHANGELOG.md
index 42423784ec87..089ba996d5cb 100644
--- a/docs/i18n/uk-UA/CHANGELOG.md
+++ b/docs/i18n/uk-UA/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/ur/CHANGELOG.md b/docs/i18n/ur/CHANGELOG.md
index 4f8dbabb437f..d2a762ded872 100644
--- a/docs/i18n/ur/CHANGELOG.md
+++ b/docs/i18n/ur/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/vi/CHANGELOG.md b/docs/i18n/vi/CHANGELOG.md
index 332c6f326c3c..8216387c5b4c 100644
--- a/docs/i18n/vi/CHANGELOG.md
+++ b/docs/i18n/vi/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/i18n/zh-CN/CHANGELOG.md b/docs/i18n/zh-CN/CHANGELOG.md
index 3ff82eb4113e..5c2741da9e85 100644
--- a/docs/i18n/zh-CN/CHANGELOG.md
+++ b/docs/i18n/zh-CN/CHANGELOG.md
@@ -4,6 +4,25 @@
---
+## [3.8.5] β 2026-05-26
+
+### π Security
+
+- **authz:** redirect `/home` and `/home/:path*` to `/login` when unauthenticated (#2712)
+
+### π§ Bug Fixes
+
+- **mcp:** break callLogs β compliance ESM cycle that deadlocks the bundled MCP server on Node.js 24 (#2650)
+- **deepseek:** guard PoW solver Web Worker handler under Node strict mode (#2724)
+- **combos:** include no-auth providers in the combo builder picker (#2737)
+- **translator:** allow the `web_search` server-tool family in the Responses API translator (#2695)
+- **oauth:** register the missing `trae` provider with `import_token` flow (#2658)
+- **model:** merge settings-based aliases with the legacy DB alias namespace (#2618, #2208)
+- **kiro:** clipboard fallback for HTTP / non-secure contexts (#2689)
+- **cli:** raise `omniroute serve` ready timeout to 60s with TCP fallback for Windows cold start (#2460)
+
+---
+
## [Unreleased]
### β¨ New Features
diff --git a/docs/reference/openapi.yaml b/docs/reference/openapi.yaml
index 6ffd6739522a..1bd8d0dc14a3 100644
--- a/docs/reference/openapi.yaml
+++ b/docs/reference/openapi.yaml
@@ -1,7 +1,7 @@
openapi: 3.1.0
info:
title: OmniRoute API
- version: 3.8.4
+ version: 3.8.5
description: |
OmniRoute is a local-first AI API proxy router. It provides an OpenAI-compatible
endpoint that routes requests to multiple AI providers with load balancing,
diff --git a/open-sse/lib/deepseek-pow-solver.cjs b/open-sse/lib/deepseek-pow-solver.cjs
index 9318ec513d14..4b4ab62722af 100644
--- a/open-sse/lib/deepseek-pow-solver.cjs
+++ b/open-sse/lib/deepseek-pow-solver.cjs
@@ -1,3 +1,3 @@
const r=(id)=>{if(id===46743)return{Buffer};return{}};const t={},e={};
-"use strict";let n,i;r(42551),r(40966),r(70968),r(76966),r(35399),r(36279),r(87801),r(16389),r(36073),r(27448),r(10681),r(32014),r(46596),r(39008),r(71),r(85540);var o=r(46743),f=Object.create,u=Object.defineProperty,s=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,c=Object.getPrototypeOf,h=Object.prototype.hasOwnProperty,l=(t,e,r)=>(r=null!=t?f(c(t)):{},((t,e,r,n)=>{if(e&&"object"==typeof e||"function"==typeof e)for(let i of a(e))h.call(t,i)||i===r||u(t,i,{get:()=>e[i],enumerable:!(n=s(e,i))||n.enumerable});return t})(!e&&t&&t.__esModule?r:u(r,"default",{value:t,enumerable:!0}),t)),p=(n=(t,e)=>{e.exports=(t,e)=>(r,n)=>{let i=2*n,o=2*e;r[i]=t[o],r[i+1]=t[o+1]}},()=>(i||n((i={exports:{}}).exports,i),i.exports)),g=l(p()),y=t=>{let{A:e,C:r}=t;for(let t=0;t<25;t+=5){for(let n=0;n<5;n++)(0,g.default)(e,t+n)(r,n);for(let n=0;n<5;n++){let i=(t+n)*2,o=(n+1)%5*2,f=(n+2)%5*2;e[i]^=~r[o]&r[f],e[i+1]^=~r[o+1]&r[f+1]}}},d=new Uint32Array([0,1,0,32898,0x80000000,32906,0x80000000,0x80008000,0,32907,0,0x80000001,0x80000000,0x80008081,0x80000000,32777,0,138,0,136,0,0x80008009,0,0x8000000a,0,0x8000808b,0x80000000,139,0x80000000,32905,0x80000000,32771,0x80000000,32770,0x80000000,128,0,32778,0x80000000,0x8000000a,0x80000000,0x80008081,0x80000000,32896,0,0x80000001,0x80000000,0x80008008]),b=t=>{let{A:e,I:r}=t,n=2*r;e[0]^=d[n],e[1]^=d[n+1]},v=[10,7,11,17,18,3,5,16,8,21,24,4,15,23,19,13,12,2,20,14,22,9,6,1],w=[1,3,6,10,15,21,28,36,45,55,2,14,27,41,56,8,25,43,62,18,39,61,20,44],x=l(p()),E=t=>{let{A:e,C:r,W:n}=t,i=0;(0,x.default)(e,i+1)(n,i);let o=0,f=0,u=0,s=32;for(;i<24;i++){let t=v[i],a=w[i];(0,x.default)(e,t)(r,0),o=n[0],f=n[1],s=32-a,n[u=a<32?0:1]=o<>>s,n[(u+1)%2]=f<>>s,(0,x.default)(n,0)(e,t),(0,x.default)(r,0)(n,0)}},m=l(p()),B=t=>{let{A:e,C:r,D:n,W:i}=t,o=0,f=0;for(let t=0;t<5;t++){let n=2*t,i=(t+5)*2,o=(t+10)*2,f=(t+15)*2,u=(t+20)*2;r[n]=e[n]^e[i]^e[o]^e[f]^e[u],r[n+1]=e[n+1]^e[i+1]^e[o+1]^e[f+1]^e[u+1]}for(let t=0;t<5;t++){(0,m.default)(r,(t+1)%5)(i,0),o=i[0],f=i[1],i[0]=o<<1|f>>>31,i[1]=f<<1|o>>>31,n[2*t]=r[(t+4)%5*2]^i[0],n[2*t+1]=r[(t+4)%5*2+1]^i[1];for(let r=0;r<25;r+=5)e[(r+t)*2]^=n[2*t],e[(r+t)*2+1]^=n[2*t+1]}},I=(t,e)=>{for(let r=0;r{for(let r=0;r>>8,e[r+2]=t[n+1]>>>16,e[r+3]=t[n+1]>>>24,e[r+4]=t[n],e[r+5]=t[n]>>>8,e[r+6]=t[n]>>>16,e[r+7]=t[n]>>>24}return e},U=function(t){let e,r,n,{capacity:i,padding:f}=t,u=i/8,s=200-i/4,a={keccak:(e=new Uint32Array(10),r=new Uint32Array(10),n=new Uint32Array(2),t=>{for(let i=1;i<24;i++)B({A:t,C:e,D:r,W:n}),E({A:t,C:e,W:n}),y({A:t,C:e}),b({A:t,I:i});e.fill(0),r.fill(0),n.fill(0)}),state:new Uint32Array(50),queue:o.Buffer.allocUnsafe(s),queueOffset:0};return this.getState=()=>a,this.setState=t=>{a.keccak=t.keccak,a.state.set(t.state.slice()),t.queue.copy(a.queue),a.queueOffset=t.queueOffset},this.absorb=t=>{for(let e=0;e=s&&(I(a.queue,a.state),a.keccak(a.state),a.queueOffset=0);return this},this.squeeze=t=>{let e={buffer:o.Buffer.allocUnsafe(u),padding:t,queue:o.Buffer.allocUnsafe(a.queue.length),state:new Uint32Array(a.state.length)};a.queue.copy(e.queue);for(let t=0;t(a.queue.fill(0),a.state.fill(0),a.queueOffset=0,this),this.copy=()=>{let t=new U({capacity:i,padding:f});return t.setState(this.getState()),t},this};onmessage=t=>{if("pow-challenge"!==t.data.type)return;let{algorithm:e,challenge:r,salt:n,difficulty:i,signature:f,expireAt:u}=t.data.challenge;try{let t=((t,e,r,n,i)=>{if("DeepSeekHashV1"!==t)throw Error("Unsupported algorithm: "+t);let f="".concat(r,"_").concat(i,"_"),u=function(t,e,r){if(t.length%2!=0)throw RangeError("c.length");if(r<=0||!Number.isSafeInteger(r))throw RangeError("d");for(var n=(function t(){var e=this;return this&&this.constructor===t?(this._sponge=new U({capacity:256}),this.update=t=>{if("string"==typeof t)return this._sponge.absorb(o.Buffer.from(t,"utf8")),this;throw TypeError("input not a string")},this.digest=function(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"hex";return e._sponge.squeeze(6).toString(t)},this.copy=()=>{let e=new t;return e._sponge=this._sponge.copy(),e},this):new t})(256).update(e),i=0;i(r=null!=t?f(c(t)):{},((t,e,r,n)=>{if(e&&"object"==typeof e||"function"==typeof e)for(let i of a(e))h.call(t,i)||i===r||u(t,i,{get:()=>e[i],enumerable:!(n=s(e,i))||n.enumerable});return t})(!e&&t&&t.__esModule?r:u(r,"default",{value:t,enumerable:!0}),t)),p=(n=(t,e)=>{e.exports=(t,e)=>(r,n)=>{let i=2*n,o=2*e;r[i]=t[o],r[i+1]=t[o+1]}},()=>(i||n((i={exports:{}}).exports,i),i.exports)),g=l(p()),y=t=>{let{A:e,C:r}=t;for(let t=0;t<25;t+=5){for(let n=0;n<5;n++)(0,g.default)(e,t+n)(r,n);for(let n=0;n<5;n++){let i=(t+n)*2,o=(n+1)%5*2,f=(n+2)%5*2;e[i]^=~r[o]&r[f],e[i+1]^=~r[o+1]&r[f+1]}}},d=new Uint32Array([0,1,0,32898,0x80000000,32906,0x80000000,0x80008000,0,32907,0,0x80000001,0x80000000,0x80008081,0x80000000,32777,0,138,0,136,0,0x80008009,0,0x8000000a,0,0x8000808b,0x80000000,139,0x80000000,32905,0x80000000,32771,0x80000000,32770,0x80000000,128,0,32778,0x80000000,0x8000000a,0x80000000,0x80008081,0x80000000,32896,0,0x80000001,0x80000000,0x80008008]),b=t=>{let{A:e,I:r}=t,n=2*r;e[0]^=d[n],e[1]^=d[n+1]},v=[10,7,11,17,18,3,5,16,8,21,24,4,15,23,19,13,12,2,20,14,22,9,6,1],w=[1,3,6,10,15,21,28,36,45,55,2,14,27,41,56,8,25,43,62,18,39,61,20,44],x=l(p()),E=t=>{let{A:e,C:r,W:n}=t,i=0;(0,x.default)(e,i+1)(n,i);let o=0,f=0,u=0,s=32;for(;i<24;i++){let t=v[i],a=w[i];(0,x.default)(e,t)(r,0),o=n[0],f=n[1],s=32-a,n[u=a<32?0:1]=o<>>s,n[(u+1)%2]=f<>>s,(0,x.default)(n,0)(e,t),(0,x.default)(r,0)(n,0)}},m=l(p()),B=t=>{let{A:e,C:r,D:n,W:i}=t,o=0,f=0;for(let t=0;t<5;t++){let n=2*t,i=(t+5)*2,o=(t+10)*2,f=(t+15)*2,u=(t+20)*2;r[n]=e[n]^e[i]^e[o]^e[f]^e[u],r[n+1]=e[n+1]^e[i+1]^e[o+1]^e[f+1]^e[u+1]}for(let t=0;t<5;t++){(0,m.default)(r,(t+1)%5)(i,0),o=i[0],f=i[1],i[0]=o<<1|f>>>31,i[1]=f<<1|o>>>31,n[2*t]=r[(t+4)%5*2]^i[0],n[2*t+1]=r[(t+4)%5*2+1]^i[1];for(let r=0;r<25;r+=5)e[(r+t)*2]^=n[2*t],e[(r+t)*2+1]^=n[2*t+1]}},I=(t,e)=>{for(let r=0;r{for(let r=0;r>>8,e[r+2]=t[n+1]>>>16,e[r+3]=t[n+1]>>>24,e[r+4]=t[n],e[r+5]=t[n]>>>8,e[r+6]=t[n]>>>16,e[r+7]=t[n]>>>24}return e},U=function(t){let e,r,n,{capacity:i,padding:f}=t,u=i/8,s=200-i/4,a={keccak:(e=new Uint32Array(10),r=new Uint32Array(10),n=new Uint32Array(2),t=>{for(let i=1;i<24;i++)B({A:t,C:e,D:r,W:n}),E({A:t,C:e,W:n}),y({A:t,C:e}),b({A:t,I:i});e.fill(0),r.fill(0),n.fill(0)}),state:new Uint32Array(50),queue:o.Buffer.allocUnsafe(s),queueOffset:0};return this.getState=()=>a,this.setState=t=>{a.keccak=t.keccak,a.state.set(t.state.slice()),t.queue.copy(a.queue),a.queueOffset=t.queueOffset},this.absorb=t=>{for(let e=0;e=s&&(I(a.queue,a.state),a.keccak(a.state),a.queueOffset=0);return this},this.squeeze=t=>{let e={buffer:o.Buffer.allocUnsafe(u),padding:t,queue:o.Buffer.allocUnsafe(a.queue.length),state:new Uint32Array(a.state.length)};a.queue.copy(e.queue);for(let t=0;t(a.queue.fill(0),a.state.fill(0),a.queueOffset=0,this),this.copy=()=>{let t=new U({capacity:i,padding:f});return t.setState(this.getState()),t},this};/* #2724: guard Web Worker handler β Node.js require() loads this CJS in strict mode where bare `onmessage = ...` throws ReferenceError */typeof self!=="undefined"&&typeof postMessage!=="undefined"&&(globalThis.onmessage=t=>{if("pow-challenge"!==t.data.type)return;let{algorithm:e,challenge:r,salt:n,difficulty:i,signature:f,expireAt:u}=t.data.challenge;try{let t=((t,e,r,n,i)=>{if("DeepSeekHashV1"!==t)throw Error("Unsupported algorithm: "+t);let f="".concat(r,"_").concat(i,"_"),u=function(t,e,r){if(t.length%2!=0)throw RangeError("c.length");if(r<=0||!Number.isSafeInteger(r))throw RangeError("d");for(var n=(function t(){var e=this;return this&&this.constructor===t?(this._sponge=new U({capacity:256}),this.update=t=>{if("string"==typeof t)return this._sponge.absorb(o.Buffer.from(t,"utf8")),this;throw TypeError("input not a string")},this.digest=function(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"hex";return e._sponge.squeeze(6).toString(t)},this.copy=()=>{let e=new t;return e._sponge=this._sponge.copy(),e},this):new t})(256).update(e),i=0;i;
const RESPONSES_STORE_MARKER = "_omnirouteResponsesStore";
const COPILOT_REASONING_SUMMARY_MARKER = "_omnirouteCopilotReasoningSummary";
+// Forward-compatible regex: matches web_search, web_search_20250305, and any future versioned names.
+const WEB_SEARCH_TOOL_TYPES = /^web_search/;
+
function toRecord(value: unknown): JsonRecord {
return value && typeof value === "object" && !Array.isArray(value) ? (value as JsonRecord) : {};
}
@@ -67,13 +70,15 @@ export function openaiResponsesToOpenAIRequest(
const tool = toRecord(toolValue);
const toolType = toString(tool.type);
// Allow: function tools, tools already in Chat format (have .function property), CLI subagent tools,
- // and namespace tools (MCP tool groups used by Codex/OpenAI Responses API).
+ // namespace tools (MCP tool groups used by Codex/OpenAI Responses API), and web_search server tools
+ // (Anthropic versioned: web_search_20250305, web_search_20250101, etc. β or plain web_search).
if (
toolType &&
toolType !== "function" &&
toolType !== "custom" &&
toolType !== "command" &&
toolType !== "namespace" &&
+ !WEB_SEARCH_TOOL_TYPES.test(toolType) &&
!tool.function
) {
throw unsupportedFeature(
@@ -255,6 +260,13 @@ export function openaiResponsesToOpenAIRequest(
result.tools = root.tools.map((toolValue) => {
const tool = toRecord(toolValue);
if (tool.function) return toolValue;
+ const toolType = toString(tool.type);
+ // Pass web_search server tools through with their original type (versioned or plain).
+ // These have no Chat Completions equivalent; preserve as-is so upstreams that understand
+ // Anthropic-style web_search_YYYYMMDD naming receive the exact name they expect.
+ if (WEB_SEARCH_TOOL_TYPES.test(toolType)) {
+ return toolValue;
+ }
return {
type: "function",
function: {
diff --git a/package-lock.json b/package-lock.json
index 688aff16b987..929734a3103c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "omniroute",
- "version": "3.8.4",
+ "version": "3.8.5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "omniroute",
- "version": "3.8.4",
+ "version": "3.8.5",
"hasInstallScript": true,
"license": "MIT",
"workspaces": [
diff --git a/package.json b/package.json
index b20a742a8e8a..884a186db3ab 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "omniroute",
- "version": "3.8.4",
+ "version": "3.8.5",
"description": "Unified AI router with 160+ providers, RTK+Caveman compression, auto fallback, MCP/A2A, desktop, PWA, and OpenAI-compatible APIs.",
"type": "module",
"bin": {
diff --git a/src/app/(dashboard)/dashboard/providers/[id]/page.tsx b/src/app/(dashboard)/dashboard/providers/[id]/page.tsx
index fef72850605a..1f123ba19ffe 100644
--- a/src/app/(dashboard)/dashboard/providers/[id]/page.tsx
+++ b/src/app/(dashboard)/dashboard/providers/[id]/page.tsx
@@ -61,6 +61,7 @@ import {
normalizeModelCatalogSource,
} from "@/shared/utils/modelCatalogSearch";
import { useCopyToClipboard } from "@/shared/hooks/useCopyToClipboard";
+import { copyToClipboard } from "@/shared/utils/clipboard";
import {
MODEL_COMPAT_PROTOCOL_KEYS,
type ModelCompatProtocolKey,
@@ -7355,11 +7356,11 @@ function AddApiKeyModal({
const copyCommandCodeValue = async (value: string | undefined, key: string) => {
if (!value) return;
- try {
- await navigator.clipboard.writeText(value);
+ const ok = await copyToClipboard(value);
+ if (ok) {
setCopiedCommandCodeField(key);
window.setTimeout(() => setCopiedCommandCodeField(null), 1500);
- } catch {
+ } else {
setSaveError("Copy failed. Select the text and copy it manually.");
}
};
diff --git a/src/lib/combos/builderOptions.ts b/src/lib/combos/builderOptions.ts
index 6bb17a8a7181..12d2add45033 100644
--- a/src/lib/combos/builderOptions.ts
+++ b/src/lib/combos/builderOptions.ts
@@ -13,6 +13,7 @@ import { getSyncedCapabilities } from "@/lib/modelsDevSync";
import { getModelsByProviderId } from "@/shared/constants/models";
import {
AI_PROVIDERS,
+ NOAUTH_PROVIDERS,
isAnthropicCompatibleProvider,
isClaudeCodeCompatibleProvider,
isOpenAICompatibleProvider,
@@ -514,6 +515,131 @@ export async function getComboBuilderOptions(): Promise();
+ const builtInModels = getModelsByProviderId(providerId);
+ const syncedModels = normalizeSyncedModels(
+ (syncedModelsMap as Record)[providerId]
+ );
+ const customModels = normalizeCustomModels(
+ (customModelsMap as Record)[providerId]
+ );
+ const fallbackModels = getCompatibleFallbackModels(providerId, builtInModels);
+ const acceptsArbitraryModel =
+ Boolean((AI_PROVIDERS[providerId] as JsonRecord | undefined)?.passthroughModels) ||
+ isOpenAICompatibleProvider(providerId) ||
+ isAnthropicCompatibleProvider(providerId) ||
+ isClaudeCodeCompatibleProvider(providerId);
+
+ for (const model of syncedModels) {
+ const resolved = getResolvedModelCapabilities({
+ provider: providerId,
+ model: toStringOrNull(model.id),
+ });
+ addModelOption(modelMap, providerId, {
+ id: toStringOrNull(model.id),
+ name: toStringOrNull(model.name),
+ source: "imported",
+ supportedEndpoints: toStringArray(model.supportedEndpoints),
+ contextLength: toNumberOrNull(model.inputTokenLimit) ?? resolved.contextWindow,
+ outputTokenLimit: toNumberOrNull(model.outputTokenLimit) ?? resolved.maxOutputTokens,
+ supportsThinking:
+ typeof model.supportsThinking === "boolean"
+ ? model.supportsThinking
+ : (resolved.supportsThinking ?? undefined),
+ });
+ }
+
+ for (const model of builtInModels as RegistryModel[]) {
+ const resolved = getResolvedModelCapabilities({
+ provider: providerId,
+ model: toStringOrNull(model.id),
+ });
+ addModelOption(modelMap, providerId, {
+ id: toStringOrNull(model.id),
+ name: toStringOrNull(model.name),
+ source: "system",
+ contextLength: toNumberOrNull(model.contextLength) ?? resolved.contextWindow,
+ outputTokenLimit: resolved.maxOutputTokens,
+ supportsThinking: resolved.supportsThinking ?? undefined,
+ });
+ }
+
+ for (const model of customModels) {
+ if (model.isHidden === true) continue;
+ const source = ["api-sync", "auto-sync", "imported"].includes(
+ toStringOrNull(model.source)?.toLowerCase() || ""
+ )
+ ? "imported"
+ : ("custom" as BuilderModelSource);
+ const resolved = getResolvedModelCapabilities({
+ provider: providerId,
+ model: toStringOrNull(model.id),
+ });
+ addModelOption(modelMap, providerId, {
+ id: toStringOrNull(model.id),
+ name: toStringOrNull(model.name),
+ source,
+ supportedEndpoints: toStringArray(model.supportedEndpoints),
+ apiFormat: toStringOrNull(model.apiFormat),
+ contextLength: toNumberOrNull(model.inputTokenLimit) ?? resolved.contextWindow,
+ outputTokenLimit: toNumberOrNull(model.outputTokenLimit) ?? resolved.maxOutputTokens,
+ supportsThinking:
+ typeof model.supportsThinking === "boolean"
+ ? model.supportsThinking
+ : (resolved.supportsThinking ?? undefined),
+ });
+ }
+
+ if (Array.isArray(fallbackModels)) {
+ for (const model of fallbackModels) {
+ const resolved = getResolvedModelCapabilities({
+ provider: providerId,
+ model: toStringOrNull(model.id),
+ });
+ addModelOption(modelMap, providerId, {
+ id: toStringOrNull(model.id),
+ name: toStringOrNull(model.name),
+ source: "fallback",
+ contextLength:
+ typeof (model as { contextLength?: number }).contextLength === "number"
+ ? (model as { contextLength?: number }).contextLength || null
+ : resolved.contextWindow,
+ outputTokenLimit: resolved.maxOutputTokens,
+ supportsThinking: resolved.supportsThinking ?? undefined,
+ });
+ }
+ }
+
+ const displayName = (providerEntryName(providerId) ||
+ getProviderDisplayName(providerId, null) ||
+ providerId) as string;
+
+ providers.push({
+ providerId,
+ providerType: providerVisual.providerType,
+ displayName,
+ alias: providerVisual.alias,
+ prefix: null,
+ icon: providerVisual.icon,
+ color: providerVisual.color,
+ source: providerVisual.source,
+ acceptsArbitraryModel,
+ connectionCount: 0,
+ activeConnectionCount: 0,
+ modelCount: modelMap.size,
+ connections: [],
+ models: Array.from(modelMap.values()).sort(compareModels),
+ });
+ }
+
const comboRefs = (combos as JsonRecord[])
.filter((combo) => combo.isHidden !== true && combo.isActive !== false)
.map((combo) => ({
diff --git a/src/lib/compliance/index.ts b/src/lib/compliance/index.ts
index b966813c8144..29b848500838 100644
--- a/src/lib/compliance/index.ts
+++ b/src/lib/compliance/index.ts
@@ -413,90 +413,10 @@ export function countAuditLog(filter: AuditLogFilter = {}) {
}
// βββ No-Log Opt-Out ββββββββββββββββ
-
-/** @type {Set} API key IDs with logging disabled */
-const noLogKeys = new Set();
-const noLogDbCache = new Map();
-let noLogColumnVerified = false;
-let hasNoLogColumn = false;
-const NO_LOG_CACHE_TTL_MS = 30_000;
-const noLogIdsFromEnv = (process.env.NO_LOG_API_KEY_IDS || "")
- .split(",")
- .map((value) => value.trim())
- .filter(Boolean);
-for (const id of noLogIdsFromEnv) {
- noLogKeys.add(id);
-}
-
-/**
- * Set whether an API key opts out of request logging.
- *
- * @param {string} apiKeyId
- * @param {boolean} noLog
- */
-export function setNoLog(apiKeyId: string, noLog: boolean) {
- if (noLog) {
- noLogKeys.add(apiKeyId);
- } else {
- noLogKeys.delete(apiKeyId);
- }
- noLogDbCache.set(apiKeyId, { value: noLog, timestamp: Date.now() });
-}
-
-function ensureNoLogColumn(db: SqliteAdapter) {
- if (noLogColumnVerified) {
- return hasNoLogColumn;
- }
-
- try {
- const columns = db.prepare("PRAGMA table_info(api_keys)").all() as Array<{ name: string }>;
- hasNoLogColumn = columns.some((column) => column.name === "no_log");
- } catch {
- hasNoLogColumn = false;
- }
-
- noLogColumnVerified = true;
- return hasNoLogColumn;
-}
-
-function readNoLogFromDb(apiKeyId: string): boolean {
- const db = getDb();
- if (!db || !apiKeyId) return false;
- if (!ensureNoLogColumn(db)) return false;
-
- const cached = noLogDbCache.get(apiKeyId);
- if (cached && Date.now() - cached.timestamp < NO_LOG_CACHE_TTL_MS) {
- return cached.value;
- }
-
- try {
- const row = db.prepare("SELECT no_log FROM api_keys WHERE id = ?").get(apiKeyId) as
- | { no_log?: number }
- | undefined;
- const value = Boolean(row && Number(row.no_log) === 1);
- noLogDbCache.set(apiKeyId, { value, timestamp: Date.now() });
- return value;
- } catch {
- return false;
- }
-}
-
-/**
- * Check if an API key has opted out of logging.
- *
- * @param {string} apiKeyId
- * @returns {boolean}
- */
-export function isNoLog(apiKeyId: string) {
- if (!apiKeyId) return false;
- if (noLogKeys.has(apiKeyId)) return true;
-
- const persistedNoLog = readNoLogFromDb(apiKeyId);
- if (persistedNoLog) {
- noLogKeys.add(apiKeyId);
- }
- return persistedNoLog;
-}
+// Moved to ./noLog.ts to break the callLogs β compliance β callLogs ESM cycle
+// that deadlocks the bundled MCP server under Node.js 24 (#2650). Re-exported
+// here so downstream callers that import from "../compliance" keep working.
+export { isNoLog, setNoLog } from "./noLog";
// βββ Log Retention / Cleanup ββββββββββββββββ
diff --git a/src/lib/compliance/noLog.ts b/src/lib/compliance/noLog.ts
new file mode 100644
index 000000000000..6b04cfd3195c
--- /dev/null
+++ b/src/lib/compliance/noLog.ts
@@ -0,0 +1,86 @@
+import type { SqliteAdapter } from "@/lib/db/adapters/types";
+import { getDbInstance } from "../db/core";
+
+// #2650: extracted from compliance/index.ts to break the
+// callLogs.ts β compliance/index.ts β callLogs.ts cycle that deadlocks
+// the bundled MCP server under Node.js 24's stricter ESM evaluation.
+
+function getDb(): SqliteAdapter | null {
+ try {
+ return getDbInstance();
+ } catch {
+ return null;
+ }
+}
+
+const noLogKeys = new Set();
+const noLogDbCache = new Map();
+let noLogColumnVerified = false;
+let hasNoLogColumn = false;
+const NO_LOG_CACHE_TTL_MS = 30_000;
+
+const noLogIdsFromEnv = (process.env.NO_LOG_API_KEY_IDS || "")
+ .split(",")
+ .map((value) => value.trim())
+ .filter(Boolean);
+for (const id of noLogIdsFromEnv) {
+ noLogKeys.add(id);
+}
+
+export function setNoLog(apiKeyId: string, noLog: boolean): void {
+ if (noLog) {
+ noLogKeys.add(apiKeyId);
+ } else {
+ noLogKeys.delete(apiKeyId);
+ }
+ noLogDbCache.set(apiKeyId, { value: noLog, timestamp: Date.now() });
+}
+
+function ensureNoLogColumn(db: SqliteAdapter): boolean {
+ if (noLogColumnVerified) {
+ return hasNoLogColumn;
+ }
+
+ try {
+ const columns = db.prepare("PRAGMA table_info(api_keys)").all() as Array<{ name: string }>;
+ hasNoLogColumn = columns.some((column) => column.name === "no_log");
+ } catch {
+ hasNoLogColumn = false;
+ }
+
+ noLogColumnVerified = true;
+ return hasNoLogColumn;
+}
+
+function readNoLogFromDb(apiKeyId: string): boolean {
+ const db = getDb();
+ if (!db || !apiKeyId) return false;
+ if (!ensureNoLogColumn(db)) return false;
+
+ const cached = noLogDbCache.get(apiKeyId);
+ if (cached && Date.now() - cached.timestamp < NO_LOG_CACHE_TTL_MS) {
+ return cached.value;
+ }
+
+ try {
+ const row = db.prepare("SELECT no_log FROM api_keys WHERE id = ?").get(apiKeyId) as
+ | { no_log?: number }
+ | undefined;
+ const value = Boolean(row && Number(row.no_log) === 1);
+ noLogDbCache.set(apiKeyId, { value, timestamp: Date.now() });
+ return value;
+ } catch {
+ return false;
+ }
+}
+
+export function isNoLog(apiKeyId: string): boolean {
+ if (!apiKeyId) return false;
+ if (noLogKeys.has(apiKeyId)) return true;
+
+ const persistedNoLog = readNoLogFromDb(apiKeyId);
+ if (persistedNoLog) {
+ noLogKeys.add(apiKeyId);
+ }
+ return persistedNoLog;
+}
diff --git a/src/lib/db/apiKeys.ts b/src/lib/db/apiKeys.ts
index 9f44fab27114..4fd42fcb3b38 100644
--- a/src/lib/db/apiKeys.ts
+++ b/src/lib/db/apiKeys.ts
@@ -8,7 +8,7 @@ import { getDbInstance, rowToCamel } from "./core";
import { backupDbFile } from "./backup";
import { registerDbStateResetter } from "./stateReset";
import { getKeyGroupsForApiKey, checkKeyModelAccess } from "./apiKeyGroups";
-import { setNoLog } from "../compliance";
+import { setNoLog } from "../compliance/noLog";
// ββββββββββββββββ Performance Optimizations ββββββββββββββββ
diff --git a/src/lib/db/detailedLogs.ts b/src/lib/db/detailedLogs.ts
index f811e751a082..7fdab54e1548 100644
--- a/src/lib/db/detailedLogs.ts
+++ b/src/lib/db/detailedLogs.ts
@@ -8,7 +8,7 @@
import { v4 as uuidv4 } from "uuid";
import { getDbInstance } from "./core";
import { getSettings } from "./settings";
-import { isNoLog } from "../compliance";
+import { isNoLog } from "../compliance/noLog";
import {
protectPayloadForLog,
serializePayloadForStorage,
diff --git a/src/lib/oauth/constants/oauth.ts b/src/lib/oauth/constants/oauth.ts
index c21fabac5de0..d829e8f7413b 100644
--- a/src/lib/oauth/constants/oauth.ts
+++ b/src/lib/oauth/constants/oauth.ts
@@ -290,6 +290,24 @@ export const CURSOR_CONFIG = {
},
};
+// Trae IDE Configuration (#2658)
+//
+// Trae is an AI-native IDE by ByteDance. Authentication is currently imported
+// token only β users sign in inside Trae and paste the resulting API token
+// here. ByteDance has not published a public OAuth client_id/secret or a CLI
+// with extractable credentials, so no automated discovery is possible yet.
+// If ByteDance ever publishes a public device-code or PKCE flow, swap
+// flowType in src/lib/oauth/providers/trae.ts and wire endpoints below.
+export const TRAE_CONFIG = {
+ apiEndpoint: "https://api.trae.ai",
+ clientType: "ide",
+ tokenStoragePaths: {
+ linux: "~/.config/Trae/User/globalStorage/state.vscdb",
+ macos: "/Users//Library/Application Support/Trae/User/globalStorage/state.vscdb",
+ windows: "%APPDATA%\\Trae\\User\\globalStorage\\state.vscdb",
+ },
+};
+
// Windsurf / Devin CLI Configuration
//
// Authentication uses PKCE Authorization Code Flow β same pattern as Codex CLI.
diff --git a/src/lib/oauth/providers/index.ts b/src/lib/oauth/providers/index.ts
index 31651dac5b58..a126b93af728 100644
--- a/src/lib/oauth/providers/index.ts
+++ b/src/lib/oauth/providers/index.ts
@@ -21,6 +21,7 @@ import { github } from "./github";
import { gitlabDuo } from "./gitlab-duo";
import { kiro } from "./kiro";
import { cursor } from "./cursor";
+import { trae } from "./trae";
import { kilocode } from "./kilocode";
import { cline } from "./cline";
import { windsurf } from "./windsurf";
@@ -39,6 +40,7 @@ export const PROVIDERS = {
kiro,
"amazon-q": kiro,
cursor,
+ trae,
kilocode,
cline,
windsurf,
diff --git a/src/lib/oauth/providers/trae.ts b/src/lib/oauth/providers/trae.ts
index f11b4edeaa5b..ddc45134c444 100644
--- a/src/lib/oauth/providers/trae.ts
+++ b/src/lib/oauth/providers/trae.ts
@@ -21,11 +21,12 @@ import { TRAE_CONFIG } from "../constants/oauth";
export const trae = {
config: TRAE_CONFIG,
flowType: "import_token",
- mapTokens: (tokens) => ({
+ mapTokens: (tokens: { accessToken: string; expiresIn?: number; machineId?: string }) => ({
accessToken: tokens.accessToken,
refreshToken: null,
expiresIn: tokens.expiresIn || 86400,
providerSpecificData: {
+ machineId: tokens.machineId,
authMethod: "imported",
},
}),
diff --git a/src/lib/usage/callLogs.ts b/src/lib/usage/callLogs.ts
index ca3329110abc..b636ea7e44f0 100644
--- a/src/lib/usage/callLogs.ts
+++ b/src/lib/usage/callLogs.ts
@@ -18,7 +18,7 @@ import {
getPromptCacheCreationTokensOrNull,
getReasoningTokensOrNull,
} from "./tokenAccounting";
-import { isNoLog } from "../compliance";
+import { isNoLog } from "../compliance/noLog";
import { sanitizePII } from "../piiSanitizer";
import { protectPayloadForLog, parseStoredPayload } from "../logPayloads";
import { getCallLogMaxEntries, getCallLogRetentionDays, getCallLogsTableMaxRows } from "../logEnv";
diff --git a/src/proxy.ts b/src/proxy.ts
index cfce41dd4726..eaa312e0911c 100644
--- a/src/proxy.ts
+++ b/src/proxy.ts
@@ -9,6 +9,8 @@ export const config = {
matcher: [
"/",
"/dashboard/:path*",
+ "/home",
+ "/home/:path*",
"/api/:path*",
"/v1/:path*",
"/v1",
diff --git a/src/server/authz/pipeline.ts b/src/server/authz/pipeline.ts
index 137d4458c708..36f0a96759c6 100644
--- a/src/server/authz/pipeline.ts
+++ b/src/server/authz/pipeline.ts
@@ -61,7 +61,12 @@ function rejectionResponse(
}
function isDashboardPath(pathname: string): boolean {
- return pathname === "/dashboard" || pathname.startsWith("/dashboard/");
+ return (
+ pathname === "/dashboard" ||
+ pathname.startsWith("/dashboard/") ||
+ pathname === "/home" ||
+ pathname.startsWith("/home/")
+ );
}
function isManagementDashboardRoute(
diff --git a/src/shared/components/KiroSocialOAuthModal.tsx b/src/shared/components/KiroSocialOAuthModal.tsx
index 3af87e72e603..ae31b6d1f738 100644
--- a/src/shared/components/KiroSocialOAuthModal.tsx
+++ b/src/shared/components/KiroSocialOAuthModal.tsx
@@ -3,6 +3,7 @@
import { useState, useEffect, useRef } from "react";
import Modal from "./Modal";
import Button from "./Button";
+import { copyToClipboard } from "@/shared/utils/clipboard";
type KiroSocialOAuthModalProps = {
isOpen: boolean;
@@ -133,7 +134,7 @@ export default function KiroSocialOAuthModal({
{authUrl.length > 80 ? authUrl.slice(0, 80) + "..." : authUrl}