Compare commits

..

3 Commits

Author SHA1 Message Date
Markus Hartung
b574f0d14e Merge remote-tracking branch 'origin/release/v3.8.51' into fix/v3850-replace-tls-client-node
# Conflicts:
#	.env.example
#	Dockerfile
#	Dockerfile.bun
#	THIRD_PARTY_NOTICES.md
#	config/quality/dependency-allowlist.json
#	docs/reference/ENVIRONMENT.md
#	docs/security/STEALTH_GUIDE.md
#	open-sse/executors/chatgpt-web.ts
#	open-sse/services/__tests__/chatgptTlsClient.test.ts
#	open-sse/services/__tests__/grokTlsClient.test.ts
#	open-sse/services/chatgptTlsClient.ts
#	package-lock.json
#	package.json
#	scripts/build/fixTlsClientNodeBinary.mjs
#	scripts/build/pack-artifact-policy.ts
#	scripts/build/postinstall.mjs
#	tests/unit/chatgpt-web.test.ts
#	tests/unit/fix-tls-client-node-binary-7802.test.ts
#	tests/unit/tls-client-download-dir-8579.test.ts
#	tests/unit/tls-client-node-docker-binary-7802.test.ts
2026-08-30 16:28:55 -03:00
diegosouzapw
31d3702a37 chore(changelog): link wreq transport migration to PR 11753 2026-08-27 02:43:56 -03:00
diegosouzapw
cb623b3cef refactor(stealth): migrate web-cookie TLS transport to wreq-js 2026-08-27 02:39:44 -03:00
293 changed files with 4417 additions and 6691 deletions

View File

@@ -1469,17 +1469,25 @@ CURSOR_USER_AGENT="Cursor/3.4"
# FIRECRAWL_BASE_URL=https://api.firecrawl.dev
# FIRECRAWL_TIMEOUT_MS=30000 # Per-request timeout (default: 30000 = 30s)
# ── Claude TLS sidecar (Chromium-fingerprinted client) ──
# Used by: open-sse/services/claudeTlsClient.ts — wire-level timeout for
# the bogdanfinn/tls-client koffi binding and the JS-side grace window
# layered on top of it when the native library is wedged.
# ── ChatGPT browser transport (Firefox-fingerprinted client) ──
# Used by: open-sse/services/chatgptTlsClient.ts — native wreq-js request
# timeout and the JS-side hard-deadline grace layered on top of it.
# OMNIROUTE_CHATGPT_TLS_TIMEOUT_MS=60000
# OMNIROUTE_CHATGPT_TLS_GRACE_MS=10000
# Max wait for the FIRST streamed byte before switching from direct streaming
# to a buffered response, in milliseconds. Default 30000 (30s). The request's
# hard deadline continues to apply while the buffered body is read.
# OMNIROUTE_CHATGPT_STREAM_FIRST_BYTE_TIMEOUT_MS=30000
# ── Claude browser transport (Chromium-fingerprinted client) ──
# Used by: open-sse/services/claudeTlsClient.ts — native wreq-js request
# timeout and the JS-side hard-deadline grace layered on top of it.
# OMNIROUTE_CLAUDE_TLS_TIMEOUT_MS=60000
# OMNIROUTE_CLAUDE_TLS_GRACE_MS=10000
# ── Perplexity TLS sidecar (Firefox-fingerprinted client) ──
# Used by: open-sse/services/perplexityTlsClient.ts — wire-level timeout for
# the bogdanfinn/tls-client koffi binding and the JS-side grace window
# layered on top of it when the native library is wedged.
# ── Perplexity browser transport (Firefox-fingerprinted client) ──
# Used by: open-sse/services/perplexityTlsClient.ts — native wreq-js request
# timeout and the JS-side hard-deadline grace layered on top of it.
# OMNIROUTE_PPLX_TLS_TIMEOUT_MS=30000
# OMNIROUTE_PPLX_TLS_GRACE_MS=10000
@@ -1491,18 +1499,16 @@ CURSOR_USER_AGENT="Cursor/3.4"
# meta-commentary. Set to 1/true/yes/on to restore the old behavior.
# OMNIROUTE_PPLX_SEARCH_HINT=0
# ── Grok web TLS sidecar (Chrome-fingerprinted client) ──
# Used by: open-sse/services/grokTlsClient.ts — wire-level timeout for the
# bogdanfinn/tls-client koffi binding and the JS-side grace window layered on
# top of it when the native library is wedged.
# ── Grok web browser transport (Chrome-fingerprinted client) ──
# Used by: open-sse/services/grokTlsClient.ts — native wreq-js request timeout
# and the JS-side hard-deadline grace layered on top of it.
# OMNIROUTE_GROK_TLS_TIMEOUT_MS=60000
# OMNIROUTE_GROK_TLS_GRACE_MS=10000
# ── Notion web TLS sidecar (Chrome-fingerprinted client) ──
# Used by: open-sse/services/notionTlsClient.ts — wire-level timeout for the
# bogdanfinn/tls-client koffi binding and the JS-side grace window layered on
# top of it when the native library is wedged. The notion-web executor raises
# the wire timeout per-request to 180000 for long generations.
# ── Notion web browser transport (Chrome-fingerprinted client) ──
# Used by: open-sse/services/notionTlsClient.ts — native wreq-js request timeout
# and the JS-side hard-deadline grace layered on top of it. The notion-web
# executor raises the native timeout per-request to 180000 for long generations.
# OMNIROUTE_NOTION_TLS_TIMEOUT_MS=30000
# OMNIROUTE_NOTION_TLS_GRACE_MS=10000

View File

@@ -237,7 +237,7 @@ jobs:
# optionals (@img/sharp-*, @img/sharp-libvips-*, @ngrok/ngrok-*,
# fsevents) carry linux forks. Replace them with the forks this
# leg's own `npm ci` resolved, then assert every bundled native
# (koffi triplets, better-sqlite3 prebuilds, wreq-js, onnxruntime)
# (better-sqlite3 prebuilds, wreq-js, onnxruntime)
# can service this leg's platform/arch before packaging starts.
run: |
node scripts/build/standaloneBundle.mjs restore --archive web-bundle.tar.gz

View File

@@ -303,12 +303,7 @@ jobs:
# #8522: file-size is base-relative on PR events (compare against
# max(frozen, base)) so inherited drift doesn't red an innocent PR;
# workflow_dispatch (no PR base) falls back to absolute comparison.
# New-code mode (Clean-as-You-Code, 2026-08-30): complexity-ratchets and
# dead-code compare the PR's files against the merge-base and block only on
# what the PR added; the global totals are advisory on PRs and re-frozen at
# release. See scripts/check/newCodeMode.mjs.
case "$g" in file-size|complexity-ratchets|dead-code) NEW_CODE=1 ;; *) NEW_CODE= ;; esac
if [ -n "$NEW_CODE" ] && [ -n "${PR_BASE_SHA:-}" ]; then
if [ "$g" = "file-size" ] && [ -n "${PR_BASE_SHA:-}" ]; then
npm run "check:$g" -- --base-ref "$PR_BASE_SHA" || failed+=("$g")
else
npm run "check:$g" || failed+=("$g")
@@ -526,10 +521,7 @@ jobs:
name: No new ESLint warnings
needs: changes
if: ${{ github.event_name != 'pull_request' || ((github.event.pull_request.draft == false || startsWith(github.head_ref, 'mergify/merge-queue/')) && needs.changes.outputs.code == 'true') }}
runs-on: ${{ (vars.USE_VPS_RUNNER == 'true' && fromJSON('["self-hosted","omni-light"]')) || 'ubuntu-latest' }}
# 2026-08-30: a cold full lint with the eslint-plugin-react-hooks 7 compiler rules is
# killed on the 7 GB hosted runner without a message (status null → exit 1, the
# JSON never written); the box lints it in ~12 min with the heap below.
runs-on: ubuntu-latest
continue-on-error: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true }}
# G0 (trilho .50): security-events:read lets the CodeQL ratchet below read open
# code-scanning alerts via `gh api .../code-scanning/alerts` (same as ci.yml's
@@ -561,8 +553,6 @@ jobs:
- name: ESLint (baseline congelado — warning novo = vermelho)
# lint:json writes the report; --max-warnings 0 keeps no-new-warnings policy.
run: npm run lint:json -- --max-warnings 0
env:
NODE_OPTIONS: --max-old-space-size=8192
# ── G0 (trilho .50): motor de ratchet também no trilho B ─────────────────────
# This job just wrote .artifacts/eslint-results.json — collect-metrics prefers
# that file, so the ratchet engine lands here at ZERO extra ESLint cost (one

View File

@@ -46,7 +46,7 @@ Repository map and Reference Documentation sections below.
## Project at a Glance
**OmniRoute** — unified AI proxy/router. One endpoint, 352 LLM providers, auto-fallback.
**OmniRoute** — unified AI proxy/router. One endpoint, 351 LLM providers, auto-fallback.
| Layer | Location | Purpose |
| ------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

View File

@@ -103,25 +103,11 @@ RUN test -f package-lock.json \
# node-gyp comes from npm's own bundled copy (deterministic, already in the image)
# instead of `npx --yes`, which would install an arbitrary registry version
# on-demand and run its lifecycle scripts (Sonar docker:S6505).
#
# tls-client-node (claude-web/grok-web/lmarena/perplexity-web TLS
# impersonation) hits the same --ignore-scripts wall: its own postinstall.js
# fetches a platform .so/.dylib/.dll from the bogdanfinn/tls-client GitHub
# Releases API and is never invoked when npm ci skips lifecycle scripts. Unlike
# better-sqlite3 above, that script never throws on failure — it only
# `console.warn`s and exits 0 — so a rate-limited or offline build would
# otherwise succeed silently with an empty bin/ and only fail at first request
# in production (TlsClientUnavailableError, #7802). Run it explicitly here so
# a broken/rate-limited fetch fails the BUILD loudly instead of shipping a
# broken image.
RUN --mount=type=cache,id=s/92ca8a61-c1ba-421f-a389-d48ac7258c2d-npm-cache,target=/root/.npm \
npm ci --include=optional --no-audit --no-fund --legacy-peer-deps --ignore-scripts \
&& (cd node_modules/better-sqlite3 \
&& node /usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js rebuild) \
&& node -e "require('better-sqlite3')(':memory:').close()" \
&& node node_modules/tls-client-node/scripts/postinstall.js \
&& (test -n "$(find node_modules/tls-client-node/bin -mindepth 1 -print -quit 2>/dev/null)" \
|| (echo "tls-client-node native binary missing after postinstall — GitHub API fetch likely rate-limited or failed (#7802)" >&2 && exit 1))
&& node -e "require('better-sqlite3')(':memory:').close()"
# Build with Turbopack (stable in Next 16, the repo default). The v3.8.27-era
# TurbopackInternalError panic ("entered unreachable code: there must be a path to a

View File

@@ -31,9 +31,9 @@ COPY scripts/dev/sync-env.mjs ./scripts/dev/sync-env.mjs
# Fast Bun native package install
RUN bun install --include=optional --quiet
# Fetch tls-client-node native binary if script exists
RUN if [ -f "node_modules/tls-client-node/scripts/postinstall.js" ] && [ ! -d "node_modules/tls-client-node/bin" ]; then \
bun node_modules/tls-client-node/scripts/postinstall.js || true; \
# Compile native better-sqlite3 Node-API addon under Bun
RUN if [ -d "node_modules/better-sqlite3" ]; then \
(cd node_modules/better-sqlite3 && bunx node-gyp rebuild); \
fi
# Smoke check native database driver used by Bun (bun:sqlite)

View File

@@ -7,7 +7,7 @@
# 🚀 OmniRoute — The Free AI Gateway
<img src="./docs/diagrams/readme-hero.svg" width="100%" alt="OmniRoute — Never stop coding. Every AI tool → 352 providers — 90+ free — through one endpoint. Claude Code, Codex, Cursor, Cline, Copilot & Antigravity into FREE Claude / GPT / Gemini with auto-fallback. RTK + Caveman stacked compression saves 1595% tokens (~89% avg) — never hit limits. 352 AI providers · 90+ free tiers · ~1.51B free tokens/mo · 19 routing strategies · $0 to start."/>
<img src="./docs/diagrams/readme-hero.svg" width="100%" alt="OmniRoute — Never stop coding. Every AI tool → 351 providers — 90+ free — through one endpoint. Claude Code, Codex, Cursor, Cline, Copilot & Antigravity into FREE Claude / GPT / Gemini with auto-fallback. RTK + Caveman stacked compression saves 1595% tokens (~89% avg) — never hit limits. 351 AI providers · 90+ free tiers · ~1.51B free tokens/mo · 19 routing strategies · $0 to start."/>
</div>
@@ -101,7 +101,7 @@
<tr>
<td align="right"><b>⚙️ Features</b></td>
<td align="center"><a href="#-combos--the-flagship">🎯 Combos</a></td>
<td align="center"><a href="#-352-ai-providers--154-catalog-marked-free">🌐 Providers</a></td>
<td align="center"><a href="#-351-ai-providers--154-catalog-marked-free">🌐 Providers</a></td>
<td align="center"><a href="#-full-cli--a2a--mcp">🔌 CLI &amp; MCP</a></td>
</tr>
<tr>
@@ -210,7 +210,7 @@ curl http://localhost:20128/v1/chat/completions \
</div>
<img src="./docs/diagrams/promise-pillars.svg" width="100%" alt="The Promise — One endpoint and 352 providers. Automatic fallback keeps routing while another healthy target is available. Six pillars: resilient fallback across 352 providers · up to 95% token savings on eligible workloads · $0 to start with 90+ free tiers and 56 recurring/keyless free-forever providers · 35 CLI/agent integrations through one config · OpenAI, Claude, Gemini and Responses API compatibility at /v1 · production controls including circuit breakers, TLS stealth, MCP 110 tools, A2A, memory, guardrails, evals and 39,000+ static test declarations across 5,100+ tracked test files."/>
<img src="./docs/diagrams/promise-pillars.svg" width="100%" alt="The Promise — One endpoint and 351 providers. Automatic fallback keeps routing while another healthy target is available. Six pillars: resilient fallback across 351 providers · up to 95% token savings on eligible workloads · $0 to start with 90+ free tiers and 56 recurring/keyless free-forever providers · 35 CLI/agent integrations through one config · OpenAI, Claude, Gemini and Responses API compatibility at /v1 · production controls including circuit breakers, TLS stealth, MCP 110 tools, A2A, memory, guardrails, evals and 39,000+ static test declarations across 5,100+ tracked test files."/>
<br/>
<br/>
@@ -461,7 +461,7 @@ All **19** strategies — mix & match per combo step:
</div>
<img src="./docs/diagrams/comparison-table.svg" width="100%" alt="What sets OmniRoute apart — a dated feature snapshot vs 9router, OpenRouter, CLIProxyAPI and LiteLLM across 13 capabilities. OmniRoute: 352 providers, 90+ free tiers built in, 19 routing strategies, 12-engine token compression, built-in MCP server with 110 tools, A2A agent protocol, persistent memory, guardrails, cloud agents, TLS fingerprint stealth, Desktop/Termux/PWA and 43 i18n UI locales. OmniRoute is MIT-licensed and self-hostable. Competitor capabilities and counts may change; see the linked methodology."/>
<img src="./docs/diagrams/comparison-table.svg" width="100%" alt="What sets OmniRoute apart — a dated feature snapshot vs 9router, OpenRouter, CLIProxyAPI and LiteLLM across 13 capabilities. OmniRoute: 351 providers, 90+ free tiers built in, 19 routing strategies, 12-engine token compression, built-in MCP server with 110 tools, A2A agent protocol, persistent memory, guardrails, cloud agents, TLS fingerprint stealth, Desktop/Termux/PWA and 43 i18n UI locales. OmniRoute is MIT-licensed and self-hostable. Competitor capabilities and counts may change; see the linked methodology."/>
<sub>📊 Full methodology &amp; per-feature detail vs 9router, OpenRouter, CLIProxyAPI &amp; LiteLLM → [`docs/comparison/OMNIROUTE_VS_ALTERNATIVES.md`](docs/comparison/OMNIROUTE_VS_ALTERNATIVES.md)</sub>
@@ -642,7 +642,7 @@ of your shell history. → [CLI Integrations](docs/guides/CLI-INTEGRATIONS.md)
<div align="center">
## 🌐 352 AI Providers — 154 Catalog-Marked Free
## 🌐 351 AI Providers — 154 Catalog-Marked Free
</div>

View File

@@ -25,6 +25,31 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FO
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
## wreq-js 3.0.0
OmniRoute distributes `wreq-js` and its seven platform-specific native addons from
[`wreq-js@3.0.0`](https://www.npmjs.com/package/wreq-js/v/3.0.0).
MIT License
Copyright (c) 2025 will-work-for-meal
Copyright (c) 2025 Oleksandr Herasymov
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
## blackwell-systems/gcf-typescript
The generic-profile codec in

View File

@@ -176,14 +176,13 @@ function isWithinRoot(ancestor, candidate) {
* Register the ESM resolve hook for the current process. Safe to call multiple
* times — subsequent calls are no-ops once the hook is installed.
*
* Modern runtimes import the hook module in-thread, initialize its root with a
* plain function call, and register its synchronous resolver through
* `module.registerHooks()`. Runtimes without that API (notably Bun) retain the
* `module.register()` worker-thread loader lifecycle path.
* Uses Node's stable `module.register()` API (available since Node 20.6,
* required Node 22+ here). The hook runs in a worker thread but only reads the
* captured `root`, so no shared-state hazards.
*
* @param {string} root Absolute path to the package root.
* @returns {Promise<boolean>} Resolves `true` once registered (or if already
* registered), `false` when neither registration API is usable.
* registered), `false` on environments where `module.register` is unavailable.
*/
let _registered = false;
export async function registerAliasResolver(root) {
@@ -202,7 +201,7 @@ export async function registerAliasResolver(root) {
}
try {
const mod = await import("node:module");
const { register } = await import("node:module");
// #7808: load the hook from a real file on disk via pathToFileURL() instead
// of building a `data:text/javascript,...` URL dynamically. CodeQL's
// `js/incomplete-url-substring-sanitization` flagged the interpolated
@@ -212,21 +211,14 @@ export async function registerAliasResolver(root) {
// package.json "files": ["bin/"].
const hookPath = join(__dirname, "aliasResolverHook.mjs");
const hookUrl = pathToFileURL(hookPath);
if (typeof mod.registerHooks === "function") {
const hook = await import(hookUrl.href);
hook.initialize({ root });
mod.registerHooks({ resolve: hook.resolve });
_registered = true;
return true;
}
mod.register(hookUrl, { data: { root } });
register(hookUrl, { data: { root } });
_registered = true;
return true;
} catch {
// Runtime or sandboxed env without a usable module hook API — fall back to
// the default resolver. The bug will resurface only in the exact
// global-install scenario, which is what we explicitly patched; other entry
// points still work because they import via relative paths.
// Older Node or sandboxed env without module.register — fall back to the
// default resolver. The bug will resurface only in the exact global-install
// scenario, which is what we explicitly patched; other entry points still
// work because they import via relative paths.
return false;
}
}

View File

@@ -1 +0,0 @@
- **fix(cli):** use in-thread alias resolver hooks on modern runtimes to avoid deprecation noise and improve Node.js forward compatibility ([#12073](https://github.com/diegosouzapw/OmniRoute/issues/12073)).

View File

@@ -0,0 +1 @@
- **chore(stealth):** replace the `tls-client-node` sidecar/temp-file transport used by the six web-cookie providers with the exactly pinned `wreq-js` 3.0.0 native transport, preserving streaming, proxy isolation, deadlines, EOF policies, binary responses, and cancellation while removing the obsolete downloader and native repair path ([#11753](https://github.com/diegosouzapw/OmniRoute/pull/11753)).

View File

@@ -74,12 +74,6 @@
"justification": "CC-BY-4.0 applies to the caniuse browser-support data (a dataset, not code). The Creative Commons Attribution license requires attribution when distributing — OmniRoute does not distribute caniuse-lite data directly to end users; it is consumed by browserslist/PostCSS at build time to generate CSS compatibility info. This is a widely accepted pattern in the Node.js ecosystem (caniuse-lite is in millions of projects). Attribution is satisfied by keeping the package in node_modules with its original license file.",
"risk": "low",
"reviewAt": "v4.0.0"
},
"tls-client-node": {
"license": "Custom: LICENSE (Apache-2.0 + Commons Clause)",
"justification": "TODO: revisar — tls-client-node uses Apache-2.0 with a 'Commons Clause' addendum that restricts 'Selling' the software (i.e., offering it as a hosted/commercial service whose value derives substantially from tls-client-node). OmniRoute is an open-source proxy; however if deployed as a paid SaaS/hosting service, this restriction could apply. The package is used by grokTlsClient.ts for Grok TLS fingerprinting. RISK: medium — legal review recommended before commercial deployment. Alternatives: consider replacing with a native TLS fingerprinting approach or a truly permissive library.",
"risk": "medium",
"reviewAt": "v3.9.0"
}
}
}

View File

@@ -133,7 +133,6 @@
"sqlite-vec",
"tailwind-merge",
"tailwindcss",
"tls-client-node",
"tsup",
"tsx",
"turndown",

View File

@@ -829,19 +829,14 @@
"src/app/(dashboard)/dashboard/HomePageClient.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 2
},
"react-hooks/exhaustive-deps": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/a2a/page.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 6
},
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/acp-agents/page.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/analytics/CompressionAnalyticsTab.tsx": {
@@ -854,26 +849,11 @@
"count": 1
}
},
"src/app/(dashboard)/dashboard/batch/components/wizard/CostEstimateStep.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/batch/components/wizard/InputStep.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/batch/components/wizard/JsonlValidationStep.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/batch/files/page.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/cli-agents/CliAgentsPageClient.tsx": {
"no-restricted-syntax": {
"count": 4
@@ -882,6 +862,9 @@
"src/app/(dashboard)/dashboard/cli-code/components/AntigravityToolCard.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 1
},
"react-hooks/exhaustive-deps": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/cli-code/components/ClineToolCard.tsx": {
@@ -909,21 +892,6 @@
"count": 6
}
},
"src/app/(dashboard)/dashboard/conductor/ConductorPageClient.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/conductor/FaroChat.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/conversations/page.tsx": {
"react-hooks/set-state-in-effect": {
"count": 2
}
},
"src/app/(dashboard)/dashboard/costs/CostOverviewTab.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 1
@@ -944,32 +912,9 @@
"count": 1
}
},
"src/app/(dashboard)/dashboard/discovery/DiscoveryPageClient.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/free-provider-rankings/page.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/health/ProviderHealthAutopilotCard.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 1
},
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/health/ProviderHealthMatrixCard.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/health/TelemetryCard.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/health/page.tsx": {
@@ -977,17 +922,9 @@
"count": 1
}
},
"src/app/(dashboard)/dashboard/log-export/LogExportPageClient.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/mcp/page.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 2
},
"react-hooks/set-state-in-effect": {
"count": 2
}
},
"src/app/(dashboard)/dashboard/onboarding/page.tsx": {
@@ -1005,16 +942,6 @@
"count": 1
}
},
"src/app/(dashboard)/dashboard/plugins/[name]/config/page.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/plugins/page.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/providers/[id]/ProviderDetailPageClient.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 2
@@ -1090,11 +1017,6 @@
"count": 1
}
},
"src/app/(dashboard)/dashboard/relay/RelayProxyClient.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/resilience/connections/components/ConnectionDetail.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 1
@@ -1105,19 +1027,6 @@
"count": 1
}
},
"src/app/(dashboard)/dashboard/resilience/connections/components/ResilienceConnectionsClient.tsx": {
"react-hooks/purity": {
"count": 1
},
"react-hooks/refs": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/runtime/components/ModelCooldownsCard.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/search-tools/components/SearchHistory.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 1
@@ -1178,6 +1087,11 @@
"count": 1
}
},
"src/app/(dashboard)/dashboard/settings/components/ProviderAccountRoutingCard.tsx": {
"react-hooks/exhaustive-deps": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/settings/components/ProxyRegistryManager.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 3
@@ -1213,21 +1127,6 @@
"count": 3
}
},
"src/app/(dashboard)/dashboard/tools/agent-bridge/components/ModelSelectorModal.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/tools/agent-bridge/components/SetupWizard.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/tools/traffic-inspector/components/CustomHostsManager.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/tools/traffic-inspector/components/RequestStreamingList.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 1
@@ -1238,11 +1137,6 @@
"count": 1
}
},
"src/app/(dashboard)/dashboard/translator/components/MonitorTab.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/translator/components/ResultNarrated.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 1
@@ -1283,26 +1177,11 @@
"count": 1
}
},
"src/app/(dashboard)/dashboard/webhooks/WebhooksPageClient.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/webhooks/__tests__/webhook-wizard.test.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/webhooks/components/AddWebhookWizard.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/webhooks/components/WebhookDeliveriesPanel.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/api/assess/route.ts": {
"@typescript-eslint/no-unused-vars": {
"count": 1
@@ -1566,21 +1445,11 @@
"count": 1
}
},
"src/app/global-error.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/login/page.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 3
}
},
"src/app/status/page.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/domain/assessment/assessor.ts": {
"@typescript-eslint/no-unused-vars": {
"count": 1
@@ -1939,7 +1808,7 @@
},
"src/lib/plugins/manager.ts": {
"@typescript-eslint/no-unused-vars": {
"count": 1
"count": 2
}
},
"src/lib/providers/validation.ts": {
@@ -2145,6 +2014,11 @@
"count": 1
}
},
"src/shared/components/ProxyConfigModal.tsx": {
"react-hooks/exhaustive-deps": {
"count": 1
}
},
"src/shared/components/ProxyLogDetail.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 1
@@ -2153,6 +2027,9 @@
"src/shared/components/RequestLoggerV2.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 3
},
"react-hooks/exhaustive-deps": {
"count": 6
}
},
"src/shared/components/RequestTimeline.tsx": {
@@ -2213,11 +2090,6 @@
"count": 1
}
},
"src/shared/hooks/cli/useToolBatchStatuses.ts": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/shared/hooks/useTheme.ts": {
"@typescript-eslint/no-unused-vars": {
"count": 1
@@ -3021,6 +2893,11 @@
"count": 1
}
},
"tests/unit/call-log-cap.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 43
}
},
"tests/unit/call-log-startup.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 1
@@ -3299,7 +3176,7 @@
},
"tests/unit/cli-nodes-commands.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 15
"count": 19
},
"@typescript-eslint/no-unused-vars": {
"count": 2
@@ -4312,11 +4189,6 @@
"count": 1
}
},
"tests/unit/injection-guard-nonchat-route-logging.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 1
}
},
"tests/unit/inspector-agent-bridge-hook.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 3
@@ -5635,32 +5507,9 @@
"count": 1
}
},
"tests/unit/ui/use-improve-prompt.test.tsx": {
"react-hooks/immutability": {
"count": 1
}
},
"tests/unit/ui/use-presets.test.tsx": {
"react-hooks/immutability": {
"count": 1
}
},
"tests/unit/ui/use-stream-metrics.test.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 1
},
"react-hooks/immutability": {
"count": 1
}
},
"tests/unit/ui/use-structured-output.test.tsx": {
"react-hooks/immutability": {
"count": 1
}
},
"tests/unit/ui/use-tools-builder.test.tsx": {
"react-hooks/immutability": {
"count": 1
}
},
"tests/unit/ui/use-traffic-stream.test.tsx": {

View File

@@ -0,0 +1,44 @@
{
"package": "wreq-js",
"version": "3.0.0",
"source": "https://registry.npmjs.org/wreq-js/-/wreq-js-3.0.0.tgz",
"npmIntegrity": "sha512-RZCoRSevVPpH4A4B4MxbFGo/pVPFveWd2gbe4ENKpPWlKXEYklZSDESOjBMmrIsmnkHh+nhM4PNJvG+NL7wBPA==",
"license": "MIT",
"nativeAddons": [
{
"path": "rust/wreq-js.darwin-arm64.node",
"size": 7690880,
"sha256": "c82eec39df691adb94f2cd09a8ff51335de8587cf132cd8b3ec797469a4b5002"
},
{
"path": "rust/wreq-js.darwin-x64.node",
"size": 8192028,
"sha256": "073b8a8a4c26aedbce7c14eef3e5567918e62e8dbf4d28296b23f9d2beec2981"
},
{
"path": "rust/wreq-js.linux-arm64-gnu.node",
"size": 8520824,
"sha256": "861d96a78caf7ce02c9ae8d37f1c59f5b0480e3142775c32917fcfe9b88524b0"
},
{
"path": "rust/wreq-js.linux-arm64-musl.node",
"size": 8735472,
"sha256": "2409a3578c8c440df419b4d5abe3ac149bec48881611a6dc1571b95e6246552d"
},
{
"path": "rust/wreq-js.linux-x64-gnu.node",
"size": 9048992,
"sha256": "55b40f4602c52111dfcdcc93db83f9d0de55d0ef7540348757709d58d05a9b64"
},
{
"path": "rust/wreq-js.linux-x64-musl.node",
"size": 8974880,
"sha256": "bd52d15b1bb4704b11561a8aa95648a6c91150082b5af0e39dd1608b7db2d317"
},
{
"path": "rust/wreq-js.win32-x64-msvc.node",
"size": 7967232,
"sha256": "7451a8701b82c946b03ba2be2f15257260a250b9e0ed9910611b22564fbec7a9"
}
]
}

View File

@@ -262,23 +262,6 @@ docs/env contract, i18n parity, unit tests) are unchanged — a red test is stil
is the early warning: a budget that fills in days means the relaxation is being consumed by
a few PRs, not by the whole team — look at the offending gate's `_rebaseline_*` notes.
**New-code mode (Clean-as-You-Code) — since 2026-08-30, PR fast-path only**
On `pull_request` events `quality.yml` passes `--base-ref <PR base SHA>` to `check:file-size`,
`check:complexity-ratchets` and `check:dead-code`. In that mode the gate compares HEAD with the
merge-base **restricted to the files the PR touched** (`scripts/check/newCodeMode.mjs`: the
merge-base is materialized in a throwaway `git worktree`, ESLint/knip run there and on HEAD, the
per-file counts are diffed):
- **blocking** — the PR added cyclomatic/cognitive violations or dead exports in files it changed
(`complexityNewCode=`, `cognitiveComplexityNewCode=`, `deadExportsNewCode=` in the log);
- **advisory** — the global total vs. the frozen baseline. Inherited drift never reds an
innocent PR; the drift is re-frozen at release reconciliation and watched by the headroom job.
`workflow_dispatch` runs, the release-green sweep and the nightly headroom job have no PR base
and keep the absolute (global) comparison. Coverage, duplication and type-coverage stay global
for now (their tools do not produce a per-file diff cheaply) — candidates for the same treatment.
**Closing the phase at v4.0 (LTS = tighter than before, not "back to normal")**
1. On the pure `release/v4.0.0` tip: `npm run quality:headroom --json` for the record, then

View File

@@ -1,4 +1,4 @@
<svg viewBox="0 0 1200 350" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Animated terminal demoing the OmniRoute CLI: omniroute providers list (352 providers registered, anthropic, codex, glm, kimi shown active), omniroute combo list (always-on priority, cost-saver, fusion-panel, context-relay) and omniroute health (healthy, 18412 requests in 24h, p95 412ms, circuit breakers 24 closed, 1 half-open, 0 open), cycling over 85 top-level commands: providers, oauth, keys, combo, nodes, models, cache, compression, cost, usage, quota, health, resilience, telemetry, logs, audit, mcp, a2a, cloud, memory, skills, eval, doctor, repl, tunnel, backup, sync, webhooks, policy, pricing, translator, simulate and more.">
<svg viewBox="0 0 1200 350" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Animated terminal demoing the OmniRoute CLI: omniroute providers list (351 providers registered, anthropic, codex, glm, kimi shown active), omniroute combo list (always-on priority, cost-saver, fusion-panel, context-relay) and omniroute health (healthy, 18412 requests in 24h, p95 412ms, circuit breakers 24 closed, 1 half-open, 0 open), cycling over 85 top-level commands: providers, oauth, keys, combo, nodes, models, cache, compression, cost, usage, quota, health, resilience, telemetry, logs, audit, mcp, a2a, cloud, memory, skills, eval, doctor, repl, tunnel, backup, sync, webhooks, policy, pricing, translator, simulate and more.">
<desc>Compact animated terminal cycling three real OmniRoute CLI commands with a typewriter effect and a scrolling subcommand ticker; the first frame shows the completed providers-list screen.</desc>
<defs><clipPath id="tickerClip"><rect x="12" y="304" width="1176" height="40"/></clipPath><clipPath id="tw0"><rect x="64" y="46" height="26" width="0"><animate attributeName="width" calcMode="discrete" values="0;31;61;92;122;153;184;214;245;245" keyTimes="0;0.012;0.018;0.024;0.030;0.036;0.042;0.048;0.054;1" dur="18s" repeatCount="indefinite"/></rect></clipPath><clipPath id="tw1"><rect x="64" y="46" height="26" width="0"><animate attributeName="width" calcMode="discrete" values="0;26;51;76;102;128;153;178;204;204" keyTimes="0;0.348;0.351;0.357;0.363;0.369;0.375;0.381;0.387;1" dur="18s" repeatCount="indefinite"/></rect></clipPath><clipPath id="tw2"><rect x="64" y="46" height="26" width="0"><animate attributeName="width" calcMode="discrete" values="0;20;41;61;82;102;122;143;163;163" keyTimes="0;0.678;0.684;0.690;0.696;0.702;0.708;0.714;0.720;1" dur="18s" repeatCount="indefinite"/></rect></clipPath></defs>
<rect width="1200" height="350" fill="#0d1117"/>

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,4 +1,4 @@
<svg viewBox="0 0 1200 780" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Comparison table: OmniRoute versus 9router, OpenRouter, CLIProxyAPI and LiteLLM across 13 capabilities. OmniRoute is the only one with the full set: 352 providers, 90+ free providers built-in, 19 routing strategies, 12-engine token compression, a built-in MCP server with 110 tools, A2A protocol, persistent memory, guardrails, cloud agents, TLS fingerprint stealth, desktop/Termux/PWA, 43 UI locales and 100% MIT self-hosted. 9router has free providers, RTK compression and translation but no MCP, A2A, memory, guardrails, cloud agents or stealth. OpenRouter is a hosted SaaS with 400+ models, guardrails and a hosted MCP but is not self-hosted and lacks A2A, memory, cloud agents and stealth. CLIProxyAPI is a light OAuth proxy with two routing strategies. LiteLLM has 100+ providers, A2A and extensive guardrails but no memory, compression, free tier, stealth or cloud agents.">
<svg viewBox="0 0 1200 780" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Comparison table: OmniRoute versus 9router, OpenRouter, CLIProxyAPI and LiteLLM across 13 capabilities. OmniRoute is the only one with the full set: 351 providers, 90+ free providers built-in, 19 routing strategies, 12-engine token compression, a built-in MCP server with 110 tools, A2A protocol, persistent memory, guardrails, cloud agents, TLS fingerprint stealth, desktop/Termux/PWA, 43 UI locales and 100% MIT self-hosted. 9router has free providers, RTK compression and translation but no MCP, A2A, memory, guardrails, cloud agents or stealth. OpenRouter is a hosted SaaS with 400+ models, guardrails and a hosted MCP but is not self-hosted and lacks A2A, memory, cloud agents and stealth. CLIProxyAPI is a light OAuth proxy with two routing strategies. LiteLLM has 100+ providers, A2A and extensive guardrails but no memory, compression, free tier, stealth or cloud agents.">
<desc>Static-header comparison table where each capability row fades in top to bottom; the OmniRoute column is highlighted and shows a check or a leading value in every row, while competitors show a mix of checks, partials and crosses.</desc>
<defs>
<pattern id="gC" width="32" height="32" patternUnits="userSpaceOnUse"><path d="M 32 0 L 0 0 0 32" fill="none" stroke="#ffffff" stroke-opacity="0.05" stroke-width="1"/></pattern>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -1,4 +1,4 @@
<svg viewBox="0 0 1200 540" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="The OmniRoute promise: one endpoint and 352 providers. Six pillars. Resilient fallback: automatic routing continues while another healthy target is available. Save up to 95 percent of eligible tokens: RTK plus Caveman stacked compression averages about 89 percent on tool-heavy sessions. Zero dollars to start: 90+ providers with a free tier and 56 recurring or keyless free-forever providers. Every tool works: 35 CLI and agent integration records, including Claude Code, Codex, Cursor, Cline, Copilot and Antigravity, through one config. One endpoint: OpenAI, Claude, Gemini and Responses API translation at /v1. Production controls: circuit breakers, TLS stealth, MCP with 110 tools, A2A, memory, guardrails, evals, and 39,000+ static test declarations across 5,100+ tracked test files.">
<svg viewBox="0 0 1200 540" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="The OmniRoute promise: one endpoint and 351 providers. Six pillars. Resilient fallback: automatic routing continues while another healthy target is available. Save up to 95 percent of eligible tokens: RTK plus Caveman stacked compression averages about 89 percent on tool-heavy sessions. Zero dollars to start: 90+ providers with a free tier and 56 recurring or keyless free-forever providers. Every tool works: 35 CLI and agent integration records, including Claude Code, Codex, Cursor, Cline, Copilot and Antigravity, through one config. One endpoint: OpenAI, Claude, Gemini and Responses API translation at /v1. Production controls: circuit breakers, TLS stealth, MCP with 110 tools, A2A, memory, guardrails, evals, and 39,000+ static test declarations across 5,100+ tracked test files.">
<desc>Animated promise card: six pillar tiles fade in in reading order, then a soft colored border highlight sweeps from tile to tile in a continuous cycle.</desc>
<defs>
<pattern id="gridPaperP" width="32" height="32" patternUnits="userSpaceOnUse">
@@ -21,7 +21,7 @@
<line x1="150" y1="53" x2="1160" y2="53" stroke="#232b38" stroke-width="1.5"/>
</g>
<g>
<text x="40" y="100" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="23" font-weight="600" fill="#c9d1d9">One endpoint. <tspan fill="#a78bfa" font-weight="800">352 providers.</tspan> Never stop building — OmniRoute picks <tspan fill="#7ee787" font-weight="700">the cheapest one that works</tspan>.</text>
<text x="40" y="100" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="23" font-weight="600" fill="#c9d1d9">One endpoint. <tspan fill="#a78bfa" font-weight="800">351 providers.</tspan> Never stop building — OmniRoute picks <tspan fill="#7ee787" font-weight="700">the cheapest one that works</tspan>.</text>
</g>
<g font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif">
@@ -38,7 +38,7 @@
<line x1="3.9" y1="3.9" x2="18.1" y2="18.1"/>
</g>
<text x="102" y="170" font-size="18" font-weight="800" fill="#74b9ff">Never hit limits</text>
<text x="66" y="204" font-size="13.5" fill="#a1a1aa">Auto-fallback across 352 providers in</text>
<text x="66" y="204" font-size="13.5" fill="#a1a1aa">Auto-fallback across 351 providers in</text>
<text x="66" y="226" font-size="13.5" fill="#a1a1aa">milliseconds. Quota out? The next provider</text>
<text x="66" y="248" font-size="13.5" fill="#a1a1aa">takes over while a healthy target remains.</text>
</g>

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -1,4 +1,4 @@
<svg viewBox="0 0 1200 548" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="OmniRoute hero: Never stop coding. Every AI tool to 352 providers — 90+ free — through one endpoint. Claude Code, Codex, Cursor, Cline, Copilot and Antigravity into free Claude, GPT and Gemini with auto-fallback. RTK + Caveman stacked compression saves 15 to 95 percent of tokens — about 89 percent average on tool-heavy sessions — so you never hit limits. Stats: 352 AI providers, 90+ free tiers, about 1.51B free tokens per month, 15 to 95 percent token savings, 19 routing strategies, zero dollars to start.">
<svg viewBox="0 0 1200 548" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="OmniRoute hero: Never stop coding. Every AI tool to 351 providers — 90+ free — through one endpoint. Claude Code, Codex, Cursor, Cline, Copilot and Antigravity into free Claude, GPT and Gemini with auto-fallback. RTK + Caveman stacked compression saves 15 to 95 percent of tokens — about 89 percent average on tool-heavy sessions — so you never hit limits. Stats: 351 AI providers, 90+ free tiers, about 1.51B free tokens per month, 15 to 95 percent token savings, 19 routing strategies, zero dollars to start.">
<desc>Animated hero card: a pulse travels the divider line and a compression bar demo repeatedly shrinks a prompt by up to 95 percent; all headline content is static and readable on the first frame.</desc>
<defs>
<pattern id="gridPaperH" width="32" height="32" patternUnits="userSpaceOnUse">
@@ -28,7 +28,7 @@
<text x="48" y="138" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="60" font-weight="800" fill="#e9edf3">Never stop coding<tspan fill="#a855f7">.</tspan></text>
<!-- subheadline -->
<text x="48" y="184" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="25" font-weight="600" fill="#c9d1d9">Every AI tool → <tspan fill="#a78bfa" font-weight="800">352 providers</tspan><tspan fill="#7ee787" font-weight="800">90+ free</tspan> — through one endpoint.</text>
<text x="48" y="184" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="25" font-weight="600" fill="#c9d1d9">Every AI tool → <tspan fill="#a78bfa" font-weight="800">351 providers</tspan><tspan fill="#7ee787" font-weight="800">90+ free</tspan> — through one endpoint.</text>
<!-- plug line -->
<text x="48" y="222" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="16.5" fill="#a1a1aa">Claude Code · Codex · Cursor · Cline · Copilot · Antigravity&#160;&#160;&#160;&#160;<tspan fill="#7ee787" font-weight="700">FREE</tspan> Claude / GPT / Gemini · auto-fallback</text>

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@@ -75,7 +75,7 @@ When you run `npm install -g omniroute`, you may see a wall of warnings like `np
The warnings come from stale peer-dependency ranges in third-party packages OmniRoute doesn't control:
1. **`marked-terminal` wants `marked >=1 <16`, found `marked@18`** — works fine in practice; the upstream peer range is just stale.
2. **`deprecated prebuild-install@7.1.3`** — the native-binary fetch helper. Only relevant later if a web-cookie provider reports a missing `tls-client-node` native binary (a separate issue, not caused by this warning).
2. **`deprecated prebuild-install@7.1.3`** — a transitive native-binary helper used by another dependency. The pinned `wreq-js@3.0.0` package bundles its seven supported platform addons directly; this warning does not diagnose the web-cookie transport.
**No action needed** — the warnings cannot be fully silenced without forking upstream packages.
@@ -148,9 +148,10 @@ desktop app, for example:
- `resources/app/.build/next/node_modules/playwright-<hash>/lib/…/agentParser.js` and
`workerProcessEntry.js` — [Playwright](https://playwright.dev), the browser-automation
library used for in-app provider login and browser-backed chat.
- `resources/app/.build/next/node_modules/tls-client-node-<hash>/bin/tls-client-windows-64-<ver>.dll`
— the native binary from `tls-client-node`, used for Cloudflare-tolerant HTTP on some web
providers.
- `resources/app/.build/next/node_modules/wreq-js-<hash>/rust/wreq-js.win32-x64-msvc.node`
— the declared MIT-licensed native addon from pinned `wreq-js@3.0.0`, used for
browser-fingerprinted HTTP on some web providers. Its expected SHA-256 is recorded in
`config/release/wreq-js-native-manifest.json`.
**Why it fires:** the Windows installer is **not yet code-signed**, so an unsigned NSIS
installer has zero reputation and behavioral heuristics run at maximum aggression. Combined

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -5,7 +5,7 @@
---
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -282,7 +282,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -763,15 +763,18 @@ REQUEST_TIMEOUT_MS (global override)
| `OMNIROUTE_PROVIDER_PROBE_TIMEOUT_MS` | `8000` | Timeout (ms) for the `validationRead` and `modelsProbe` presets in `src/shared/network/safeOutboundFetch.ts`. Raise for slow endpoints (Cerebras, Cloudflare AI, Groq) to prevent flapping between active/error in the dashboard. Falls back to 8000ms for invalid (<1000) or non-numeric values. |
| `OMNIROUTE_RELAY_FETCH_TIMEOUT_MS` | `25000` | Relay-specific fetch timeout in `open-sse/utils/proxyFetch.ts` (#9158). A hung relay must fail before the client/agent timeout (~30s) so callers see a relay-specific failure instead of a generic upstream timeout. Capped at `29000` so it always fires first. |
| `OMNIROUTE_RETRY_BACKOFF_MS` | `10` | Shared retry backoff for the direct/relay/proxy retry-once paths in `open-sse/utils/proxyFetch.ts` (#9158). `0` = retry immediately. |
| `OMNIROUTE_CLAUDE_TLS_TIMEOUT_MS` | `60000` | Wire-level timeout for the bogdanfinn/tls-client koffi binding (`claudeTlsClient.ts`). |
| `OMNIROUTE_CLAUDE_TLS_GRACE_MS` | `10000` | JS-side grace added on top of the wire timeout when the native binding is wedged. |
| `OMNIROUTE_PPLX_TLS_TIMEOUT_MS` | `30000` | Wire-level timeout for the bogdanfinn/tls-client koffi binding (`perplexityTlsClient.ts`). |
| `OMNIROUTE_PPLX_TLS_GRACE_MS` | `10000` | JS-side grace added on top of the wire timeout when the native binding is wedged. |
| `OMNIROUTE_CHATGPT_TLS_TIMEOUT_MS` | `60000` | Native wreq-js request timeout (`chatgptTlsClient.ts`). |
| `OMNIROUTE_CHATGPT_TLS_GRACE_MS` | `10000` | JS-side hard-deadline grace added on top of the native timeout. |
| `OMNIROUTE_CHATGPT_STREAM_FIRST_BYTE_TIMEOUT_MS` | `30000` (30s) | Max wait for the first streamed byte before ChatGPT switches to a buffered response; the hard request deadline remains active. |
| `OMNIROUTE_CLAUDE_TLS_TIMEOUT_MS` | `60000` | Native wreq-js request timeout (`claudeTlsClient.ts`). |
| `OMNIROUTE_CLAUDE_TLS_GRACE_MS` | `10000` | JS-side hard-deadline grace added on top of the native timeout. |
| `OMNIROUTE_PPLX_TLS_TIMEOUT_MS` | `30000` | Native wreq-js request timeout (`perplexityTlsClient.ts`). |
| `OMNIROUTE_PPLX_TLS_GRACE_MS` | `10000` | JS-side hard-deadline grace added on top of the native timeout. |
| `OMNIROUTE_PPLX_SEARCH_HINT` | `0` (off) | Appends "You have built-in web search. Answer questions directly using search results." to the caller's system message (`perplexity-web/protocol.ts`). Off by default — Perplexity searches anyway, and the sentence leaks into replies as meta-commentary for coding clients. Set `1`/`true`/`yes`/`on` to restore. |
| `OMNIROUTE_GROK_TLS_TIMEOUT_MS` | `60000` | Wire-level timeout for the bogdanfinn/tls-client koffi binding (`grokTlsClient.ts`). |
| `OMNIROUTE_GROK_TLS_GRACE_MS` | `10000` | JS-side grace added on top of the wire timeout when the native binding is wedged. |
| `OMNIROUTE_NOTION_TLS_TIMEOUT_MS` | `30000` | Wire-level timeout for the bogdanfinn/tls-client koffi binding (`notionTlsClient.ts`); the `notion-web` executor raises it per-request to `180000` for long generations. |
| `OMNIROUTE_NOTION_TLS_GRACE_MS` | `10000` | JS-side grace added on top of the wire timeout when the native binding is wedged. |
| `OMNIROUTE_GROK_TLS_TIMEOUT_MS` | `60000` | Native wreq-js request timeout (`grokTlsClient.ts`). |
| `OMNIROUTE_GROK_TLS_GRACE_MS` | `10000` | JS-side hard-deadline grace added on top of the native timeout. |
| `OMNIROUTE_NOTION_TLS_TIMEOUT_MS` | `30000` | Native wreq-js request timeout (`notionTlsClient.ts`); `notion-web` raises it per request to `180000` for long generations. |
| `OMNIROUTE_NOTION_TLS_GRACE_MS` | `10000` | JS-side hard-deadline grace added on top of the native timeout. |
| `OMNIROUTE_BROWSER_POOL` | `on` | Shared Playwright browser pool for browser-backed web-cookie chat (`browserPool.ts`); set `off` to disable. |
| `WEB_COOKIE_USE_BROWSER` | `0` | Opt a web-cookie chat request into the browser-backed path (`browserBackedChat.ts`); `1` to enable. |
| `KIMI_WEB_BASE_URL` | `https://www.kimi.ai` | Base URL for the Kimi Web (international kimi.ai Connect-RPC) executor (`kimi-web.ts`); override only for mirror/proxy endpoints. |
@@ -1077,7 +1080,6 @@ Anthropic-compatible provider instead.
| `PROXY_AUTO_DISABLE` | `false` | `src/lib/proxyHealth/scheduler.ts` | Set `true` to let the scheduler soft-disable (status `dead`, never deleted) a proxy after repeated consecutive failures, instead of removing it. Non-destructive alternative to `PROXY_AUTO_REMOVE`: the proxy drops out of pool/rotation resolution immediately (the alive-status filter used by scope-pool resolution already excludes it) and is automatically re-activated once it starts passing probes again. Shares the `PROXY_AUTO_REMOVE_AFTER` threshold. If both flags are `true`, `PROXY_AUTO_REMOVE` wins. |
| `OMNIROUTE_CONTROL_PLANE_PROXY_DIRECT_FALLBACK` | `false` | `src/shared/constants/featureFlagDefinitions.ts` | Allow OAuth and provider validation flows to bypass a pinned proxy and connect directly when proxy reachability pre-checks fail. Effective precedence is Feature Flags DB override > env var > default. |
| `RATE_LIMIT_MAX_WAIT_MS` | `15000` (15s) | `open-sse/services/rateLimitManager.ts` | Max time to wait on a 429 before failing the request. |
| `RATE_LIMIT_EXECUTION_MAX_WAIT_MS` | `600000` (10 min) | `open-sse/services/rateLimitManager.ts` | Ceiling for how long an admitted request may stay in execution before its rate-limit reservation expires — decoupled from the queue-wait budget so slow fetch-start on non-incremental gateways does not time out (#12027). |
| `RATE_LIMIT_MAX_QUEUE_DEPTH` | `0` (disabled) | `open-sse/services/rateLimitManager.ts` | Queue admission cap: reject with a 429 `queue_full` once this many requests are already queued. `0` = unbounded (default). |
| `RATE_LIMIT_AUTO_ENABLE` | _(unset)_ | `open-sse/services/rateLimitManager.ts` | Force the auto-enable rate limit safety net on/off regardless of the persisted Dashboard setting. Accepts `true`/`1`/`on` to force on, `false`/`0`/`off` to force off. |
| `PROVIDER_COOLDOWN_ENABLED` | _(unset → off)_ | `open-sse/services/providerCooldownTracker.ts` | Opt-in global cross-request provider/connection cooldown tracking. OFF by default (overlaps Connection Cooldown / Provider Circuit Breaker). Accepts `true`/`1`/`on` to enable. |

View File

@@ -1,13 +1,13 @@
---
title: "Stealth Guide"
version: 3.8.40
lastUpdated: 2026-06-28
version: 3.8.50
lastUpdated: 2026-08-26
---
# Stealth Guide
> **Source of truth:** `open-sse/utils/tlsClient.ts`, `open-sse/services/{claudeCodeCCH,claudeCodeFingerprint,claudeCodeObfuscation,claudeCodeCompatible}.ts`, `open-sse/config/cliFingerprints.ts`, `src/mitm/`
> **Last updated:** 2026-06-28 — v3.8.40
> **Source of truth:** `open-sse/utils/tlsClient.ts`, `open-sse/services/{tlsClientBase,chatgptTlsClient,claudeTlsClient,perplexityTlsClient,grokTlsClient,notionTlsClient,lmarenaTlsClient,claudeCodeCCH,claudeCodeFingerprint,claudeCodeObfuscation,claudeCodeCompatible}.ts`, `open-sse/config/cliFingerprints.ts`, `src/mitm/`
> **Last updated:** 2026-08-26 — v3.8.50
> **Audience:** Engineers maintaining provider-specific stealth integrations.
OmniRoute integrates with providers whose edges actively fingerprint non-official clients (TLS JA3/JA4, header ordering, JSON body shape, integrity tokens). This page documents the stealth surfaces OmniRoute exposes and where they are implemented.
@@ -29,6 +29,41 @@ Lazy-loaded `wreq-js` session that impersonates **Chrome 124 on macOS**. Used as
- Timeout: `TLS_CLIENT_TIMEOUT_MS` (inherits from `FETCH_TIMEOUT_MS`, default 600000)
- `wreq-js` Response is fetch-compatible (`headers`, `text()`, `json()`, `clone()`, `body`).
### Web-cookie provider transport — wreq-js 3.0.0
`open-sse/services/tlsClientBase.ts` is the shared transport for ChatGPT, Claude, Perplexity,
Grok, Notion, and LMArena web sessions. Each thin provider wrapper selects a browser/OS profile;
the base loads `wreq-js` lazily, reuses only transport-level connections keyed by
profile + OS + resolved proxy, and gives every request an ephemeral cookie scope. It never shares a
wreq session or cookie jar between accounts or requests.
| Provider | Profile | Emulated OS | Stream EOF policy |
| ---------- | ------------- | ----------- | -------------------------------- |
| ChatGPT | `firefox_148` | macOS | include `[DONE]` |
| Claude | `chrome_146` | Linux | include `[DONE]` |
| Perplexity | `firefox_148` | macOS | include `event: end_of_stream` |
| Grok | `chrome_146` | Linux | exclude `[DONE]` |
| Notion | `chrome_146` | Windows | include `[DONE]` |
| LMArena | `chrome_146` | Windows | no sentinel; close on native EOF |
- Streaming uses the native response `ReadableStream` directly; no temp file or sidecar is created.
- Up to 256 initial bytes are inspected before exposing a stream. SSE providers buffer non-SSE
errors; Grok/LMArena map Cloudflare challenges to `403` and HTML interstitials to `502`.
- The native request timeout remains wrapped by an absolute JS hard deadline. A hang invalidates
and closes only the affected profile/OS/proxy transport before the next request recreates it.
- Proxy resolution priority is per-call `proxyUrl` → request-scoped account/dashboard context →
`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY` (including lowercase variants). Resolution errors fail
closed instead of leaking a direct connection. LMArena deliberately resolves against `arena.ai`.
- `byteResponse` returns a content-typed `data:` URL without UTF-8 corruption.
- Errors are `TlsClientUnavailableError` (package/addon unavailable) and `TlsClientHangError`
(deadline exceeded).
The profiles are supported by the pinned package, but real WAF acceptance can change independently
of local contract tests. Validate fingerprint changes against an explicitly authorized live account
before claiming parity with an upstream browser.
---
## Claude Code Stealth Bundle
When `cliCompatMode` is on, OmniRoute reshapes outgoing Claude requests so they are indistinguishable from `claude-cli` traffic. Three modules collaborate:

View File

@@ -1,6 +1,6 @@
# OmniRoute
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 352 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 351 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (110 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
## Overview
@@ -277,7 +277,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
## Key Features (v3.8.50)
### Core Proxy
- **352 AI providers** with automatic format translation
- **351 AI providers** with automatic format translation
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
- **4-tier fallback**: Subscription → API Key → Cheap → Free

View File

@@ -132,9 +132,7 @@ const nextConfig = {
// instead of keeping the old generation in control. Falls back to a
// value that is unique per build run when git is absent (CI tarball).
NEXT_PUBLIC_SW_BUILD_ID:
process.env.OMNIROUTE_SW_BUILD_ID ||
process.env.SOURCE_VERSION ||
`${Date.now()}`,
process.env.OMNIROUTE_SW_BUILD_ID || process.env.SOURCE_VERSION || `${Date.now()}`,
},
distDir,
// Turbopack config: redirect native modules to stubs at build time
@@ -307,9 +305,6 @@ const nextConfig = {
"keytar",
"wreq-js",
"zod",
"tls-client-node",
"koffi",
"tough-cookie",
"@ngrok/ngrok",
"@huggingface/transformers",
// copilot-m365-web.ts imports 'ws' as a client-side WebSocket. When bundled,

View File

@@ -175,7 +175,6 @@ export const HTTP_STATUS = {
REQUEST_TIMEOUT: 408,
GONE: 410,
RATE_LIMITED: 429,
PLAN_LIMIT_EXCEEDED: 432,
SERVER_ERROR: 500,
BAD_GATEWAY: 502,
SERVICE_UNAVAILABLE: 503,

View File

@@ -190,13 +190,6 @@ export const VIDEO_PROVIDERS: Record<string, VideoProvider> = {
authType: "apikey",
authHeader: "bearer",
format: "pollinations-video",
// Живая проверка 2026-08-30: диспетчер videoGeneration.ts не разбирает
// "pollinations-video" и отвечает 400 Unsupported video format — модель
// висела в выдаче каталога, но не исполнялась ни при каких ключах.
unsupported: true,
unsupportedReason:
"Pollinations video has no submit/poll transport in the dispatcher yet. " +
"Use an image model or another video provider until one is added.",
models: [{ id: "default", name: "Pollinations Video (Free)" }],
},
@@ -207,12 +200,6 @@ export const VIDEO_PROVIDERS: Record<string, VideoProvider> = {
authType: "apikey",
authHeader: "bearer",
format: "minimax-video",
// Живая проверка 2026-08-30: 400 Unsupported video format на всех трёх
// моделях Hailuo. Свой submit → query API, не покрытый job-пресетами.
unsupported: true,
unsupportedReason:
"MiniMax video uses its own submit/query transport that the dispatcher " +
"does not implement yet. Generate video via another provider for now.",
models: [
{ id: "MiniMax-Hailuo-2.3", name: "Hailuo 2.3" },
{ id: "MiniMax-Hailuo-02", name: "Hailuo 02" },
@@ -227,12 +214,6 @@ export const VIDEO_PROVIDERS: Record<string, VideoProvider> = {
authType: "apikey",
authHeader: "bearer",
format: "together-video",
// Не рекламируется по той же причине, что pollinations/minimax: формат
// объявлен, ветки в диспетчере нет (проверено разбором 2026-08-30).
unsupported: true,
unsupportedReason:
"Together video has no transport in the dispatcher yet. " +
"Use another video provider until one is added.",
models: [
{ id: "wan-ai/wan2.1-t2v-480p", name: "Wan 2.1 T2V 480p" },
{ id: "wan-ai/wan2.7-t2v", name: "Wan 2.7 T2V" },
@@ -246,12 +227,6 @@ export const VIDEO_PROVIDERS: Record<string, VideoProvider> = {
authType: "apikey",
authHeader: "bearer",
format: "replicate-video",
// Не рекламируется: формат объявлен, ветки в диспетчере нет
// (проверено разбором 2026-08-30).
unsupported: true,
unsupportedReason:
"Replicate video has no prediction submit/poll transport in the " +
"dispatcher yet. Use another video provider until one is added.",
models: [
{ id: "minimax/video-01", name: "MiniMax Video 01" },
{ id: "wan-ai/wan2.1-t2v-480p", name: "Wan 2.1 T2V" },
@@ -419,20 +394,7 @@ export const VIDEO_PROVIDERS: Record<string, VideoProvider> = {
baseUrl: "https://nano-gpt.com/api/v1/video/generations",
authType: "apikey",
authHeader: "bearer",
// Диспетчер знает формат под именем "openai-video" — под "openai" ветки нет,
// и провайдер отдавал 400 Unsupported video format (живая проверка
// 2026-08-30). Тот же обработчик обслуживает кастомные OpenAI-совместимые
// ноды, а baseUrl выше — ровно их путь.
format: "openai-video",
// Живая проверка 2026-08-30: адрес выше отдаёт 404 (HTML-страница), как и
// вариант во множественном числе /api/v1/videos/generations. Контроль на том
// же ключе: /api/v1/images/generations отвечает 401 JSON — то есть 404 здесь
// значит «маршрута нет», а не «ключ не тот». Формат исправлен на рабочее имя
// заранее, чтобы провайдер ожил правкой одного адреса, когда он появится.
unsupported: true,
unsupportedReason:
"NanoGPT video endpoint returns 404 — no video route is published under " +
"/api/v1/video(s)/generations. Use another video provider.",
format: "openai",
models: [{ id: "default", name: "NanoGPT Video" }],
},
};

View File

@@ -939,8 +939,8 @@ export class GrokWebExecutor extends BaseExecutor {
// Fetch from Grok via TLS-impersonating client (#3180).
// Grok sits behind Cloudflare Enterprise which rejects Node's native TLS
// fingerprint even with valid sso+sso-rw cookies. We use tls-client-node
// to send a Chrome-like handshake instead.
// fingerprint even with valid sso+sso-rw cookies. The pinned wreq-js
// transport sends a Chrome-like handshake instead.
let tlsResult: TlsFetchResult;
try {
tlsResult = await tlsFetchGrok(GROK_CHAT_API, {

View File

@@ -2,8 +2,8 @@
* LMArenaExecutor — Arena (formerly LMArena) web-session provider.
*
* Routes requests through arena.ai create-evaluation with session cookies.
* Upstream sits behind Cloudflare; traffic goes through tls-client-node Chrome
* impersonation (see services/lmarenaTlsClient.ts).
* Upstream sits behind Cloudflare; traffic goes through wreq-js Chrome
* impersonation with isolated ephemeral cookies (see services/lmarenaTlsClient.ts).
*
* Helpers: open-sse/executors/lmarena/{cookie,models,stream,response}.ts
*/
@@ -174,7 +174,6 @@ export class LMArenaExecutor extends BaseExecutor {
body: JSON.stringify(transformedBody),
signal: ctx.signal,
stream: ctx.stream,
streamEofSymbol: "__OMNIROUTE_LMARENA_EOF_NEVER__",
});
const failed = mapFailedTlsResult({

View File

@@ -6,9 +6,9 @@ export const LMARENA_API_BASE = "https://arena.ai";
export const LMARENA_STREAM_URL = `${LMARENA_API_BASE}/nextjs-api/stream/create-evaluation`;
/**
* Current Chrome stable UA (header surface).
* TLS JA3 profile is separate: tls-client-node tops out at chrome_146 — see
* LMARENA_PROFILE in lmarenaTlsClient.ts. Headers track the live browser string;
* fingerprint stays at the newest native profile we can actually impersonate.
* TLS JA3/JA4 profile is separate: the provider-tested wreq-js profile is pinned
* to chrome_146 in lmarenaTlsClient.ts while headers track the live browser string.
* Treat that deliberate version skew as a WAF-sensitive compatibility surface.
*/
export const LMARENA_USER_AGENT =
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36";

View File

@@ -114,7 +114,7 @@ export function mapTlsUnavailable(
return {
response: errorResponse(
502,
`Arena TLS impersonation unavailable: ${error.message}. Install/repair tls-client-node native binary.`,
`Arena TLS impersonation unavailable: ${error.message}. Verify the wreq-js 3.0.0 native addon.`,
"upstream_error",
"TLS_CLIENT_UNAVAILABLE"
),

View File

@@ -22,7 +22,7 @@
* chunk — safer than assuming unverified incremental-delta semantics.
*
* Auth: Cookie-based (token_v2 [+ optional space_id, notion_browser_id, user_id])
* Method: Browser-TLS impersonation via tls-client-node (Chrome JA3). Plain
* Method: Browser-TLS impersonation via pinned wreq-js (Chrome JA3/JA4). Plain
* Node/undici fetch is rejected by Notion's edge with in-band
* `temporarily-unavailable` (HTTP 200, empty assistant text) — curl/Schannel
* and Chrome work with the same cookie + body. See services/notionTlsClient.ts.
@@ -60,10 +60,7 @@ import {
messagesForNotionTranscript,
type NotionAgentOptions,
} from "../services/notionTranscriptBuilder.ts";
import {
tlsFetchNotion,
TlsClientUnavailableError,
} from "../services/notionTlsClient.ts";
import { tlsFetchNotion, TlsClientUnavailableError } from "../services/notionTlsClient.ts";
// Re-exported for unit tests that destructure `mod.<name>` on this module.
export {
@@ -225,7 +222,6 @@ function extractUserIdFromCookie(cookie: string): string {
return extractNotionUserIdFromCookie(cookie);
}
/**
* Notion's undocumented inference API does not return token usage.
* Emit a cheap char-based estimate so clients don't see a constant
@@ -236,9 +232,7 @@ export function estimateNotionUsage(
messages: NotionMessage[] | undefined,
content: string
): { prompt_tokens: number; completion_tokens: number; total_tokens: number; estimated: true } {
const promptText = (messages || [])
.map((m) => extractNotionMessageText(m?.content))
.join("\n");
const promptText = (messages || []).map((m) => extractNotionMessageText(m?.content)).join("\n");
// ~4 chars/token (English-ish); at least 1 when there is any text.
const prompt_tokens = promptText ? Math.max(1, Math.ceil(promptText.length / 4)) : 0;
const completion_tokens = content ? Math.max(1, Math.ceil(content.length / 4)) : 0;
@@ -393,9 +387,8 @@ function buildNotionExecuteHeaders(opts: {
const isCustom = Boolean(opts.agent?.workflowId);
// Browser uses /agent/<workflowId without dashes>?wfv=chat for custom agents.
const agentPathId = (opts.agent?.workflowId || "").replace(/-/g, "");
const referer = isCustom && agentPathId
? `${BASE_URL}/agent/${agentPathId}?wfv=chat`
: `${BASE_URL}/ai`;
const referer =
isCustom && agentPathId ? `${BASE_URL}/agent/${agentPathId}?wfv=chat` : `${BASE_URL}/ai`;
const reqHeaders: Record<string, string> = {
"Content-Type": "application/json",
"User-Agent": USER_AGENT,
@@ -453,11 +446,8 @@ export function resolveNotionAgentOptions(
"agent_id",
]) || "";
const pageFromPs =
readProviderSpecificString(ps, [
"contextPageId",
"context_page_id",
"notionContextPageId",
]) || "";
readProviderSpecificString(ps, ["contextPageId", "context_page_id", "notionContextPageId"]) ||
"";
const readCookie = (name: string): string => {
const m = cookie.match(new RegExp(`(?:^|;\\s*)${name}=([^;]+)`, "i"));
@@ -477,10 +467,7 @@ export function resolveNotionAgentOptions(
readCookie("agent_id")
);
const contextPageId =
pageFromPs ||
readCookie("context_page_id") ||
readCookie("notion_context_page_id") ||
"";
pageFromPs || readCookie("context_page_id") || readCookie("notion_context_page_id") || "";
return {
workflowId: workflowId || undefined,
@@ -510,8 +497,7 @@ async function sendNotionInferenceRequest(opts: {
body: JSON.stringify(reqBody),
signal: signal ?? undefined,
// Inference can take a while (tool-autoload + LLM first token).
timeoutMs:
Number.parseInt(process.env.OMNIROUTE_NOTION_TLS_TIMEOUT_MS || "", 10) || 180_000,
timeoutMs: Number.parseInt(process.env.OMNIROUTE_NOTION_TLS_TIMEOUT_MS || "", 10) || 180_000,
});
status = tlsRes.status;
rawText = tlsRes.text ?? "";
@@ -634,8 +620,7 @@ export class NotionWebExecutor extends BaseExecutor {
const inboundHeaders =
(input.clientHeaders as Record<string, string> | null | undefined) ??
((input as { headers?: Record<string, string> }).headers as
| Record<string, string>
| undefined);
Record<string, string> | undefined);
const clientThreadId = readClientThreadId(requestBody, inboundHeaders ?? undefined);
// Namespace the thread cache PER CALLER (hash of the caller's cookie) AND by custom
// agent, so (a) two users of the same Notion space never share a cached thread
@@ -738,7 +723,10 @@ export class NotionWebExecutor extends BaseExecutor {
// One automatic retry for transient Notion faults — same threadId, never create again
if (isFailedAttempt(attempt) && attempt.retryable) {
const delayMs = process.env.NODE_ENV === "test" || process.env.VITEST ? 20 : 700 + Math.floor(Math.random() * 400);
const delayMs =
process.env.NODE_ENV === "test" || process.env.VITEST
? 20
: 700 + Math.floor(Math.random() * 400);
await new Promise((r) => setTimeout(r, delayMs));
attempt = await runOnce({ createThread: false, threadId });
}

View File

@@ -501,7 +501,7 @@ export class PerplexityWebExecutor extends BaseExecutor {
if (isCloudflareChallenge(response.text)) {
errMsg =
"Cloudflare blocked the request — Perplexity's edge rejected this server's TLS fingerprint " +
"(common on VPS/datacenter IPs). Ensure tls-client-node is installed with its native binary, " +
"(common on VPS/datacenter IPs). Verify the wreq-js 3.0.0 native addon, " +
"or route perplexity-web through a residential proxy.";
log?.error?.("PPLX-WEB", "Cloudflare challenge detected — TLS bypass failed");
} else {

View File

@@ -131,7 +131,7 @@ import { resolveChatCoreRequestFormat } from "./chatCore/requestFormat.ts";
import { resolveChatCoreTargetFormat } from "./chatCore/targetFormat.ts";
import { resolveOmniGlyphTransport } from "../services/compression/imageTransportPolicy.ts";
import { stripStore, usesClaudeBridge } from "./chatCore/agentRouterProtocol.ts";
import { normalizeClaudeToolsForDispatch } from "./chatCore/claudeToolDefaults.ts";
import { defaultClaudeToolType } from "./chatCore/claudeToolDefaults.ts";
import { injectSystemPrompt, injectCustomSystemPrompt } from "../services/systemPrompt.ts";
import { translateRequest, needsTranslation } from "../translator/index.ts";
import { FORMATS } from "../translator/formats.ts";
@@ -2615,13 +2615,9 @@ export async function handleChatCore({
// definitions that omit the required `type` discriminator with HTTP 400. Default
// a missing `type` to "custom" before dispatch, mirroring Anthropic's own
// inference, so legacy Claude-format tool payloads survive strict gateways (#2195).
// AgentRouter is the opposite quirk: its Rust deserializer only accepts versioned
// tool types and 400s on `type: "custom"` — there the discriminator is stripped
// instead (see claudeToolDefaults.ts).
if (targetFormat === FORMATS.CLAUDE && Array.isArray(translatedBody.tools)) {
translatedBody.tools = normalizeClaudeToolsForDispatch(
translatedBody.tools,
provider
translatedBody.tools = defaultClaudeToolType(
translatedBody.tools
) as typeof translatedBody.tools;
}

View File

@@ -25,41 +25,3 @@ export function defaultClaudeToolType(tools: unknown): unknown {
return tool;
});
}
/**
* Strip the `type: "custom"` discriminator from Claude-format tools, leaving every
* other field (name, description, input_schema, …) untouched. AgentRouter's upstream
* (New-API, Rust serde) only accepts versioned tool types (`web_search_20250305`,
* `web_search_20260209`); plain tools must omit `type` entirely, so `type: "custom"` —
* whether client-declared (Claude Code v2.1+) or backfilled by defaultClaudeToolType()
* (#2195) — is a hard 400 "unknown variant `custom`" that crashes the client session.
* Versioned/built-in types are preserved; typeless entries stay typeless. Non-object
* entries pass through untouched (same rationale as defaultClaudeToolType).
*/
export function stripClaudeCustomToolType(tools: unknown): unknown {
if (!Array.isArray(tools)) return tools;
return tools.map((tool) => {
if (
tool &&
typeof tool === "object" &&
!Array.isArray(tool) &&
(tool as UnknownRecord).type === "custom"
) {
const { type: _stripped, ...rest } = tool as UnknownRecord;
return rest;
}
return tool;
});
}
/**
* Per-provider dispatch decision for Claude-format tool normalization. AgentRouter
* rejects `type: "custom"` (see stripClaudeCustomToolType) while strict gateways like
* MiniMax REQUIRE the explicit discriminator (#2195) — the two quirks are mutually
* exclusive, so the normalization is provider-scoped, never global.
*/
export function normalizeClaudeToolsForDispatch(tools: unknown, provider: string): unknown {
return provider === "agentrouter"
? stripClaudeCustomToolType(tools)
: defaultClaudeToolType(tools);
}

View File

@@ -17,11 +17,7 @@ import {
} from "./aihordeMapRequest.ts";
const GENERATE_TIMEOUT_MS = 600_000;
// Опрос начинается частым и разряжается по мере ожидания: короткая очередь
// отдаёт картинку за секунды, а длинная иначе стоила бы Horde сотен запросов
// по общему анонимному ключу (600 опросов на один кадр при полном бюджете).
const POLL_INTERVAL_MIN_MS = 1_000;
const POLL_INTERVAL_MAX_MS = 8_000;
const POLL_INTERVAL_MS = 1_000;
// Per-call bound for the Horde API's own submit/check/status/cancel calls
// (a fixed, trusted host — no SSRF guard needed, just a hard timeout so a
// hung upstream cannot stall a request indefinitely). Individual calls are
@@ -123,11 +119,6 @@ async function fetchHordeImageBytes(
return value;
}
/** Числовое поле ответа Horde: отсутствующее или нечисловое читается как «неизвестно». */
function numericField(value: unknown): number | null {
return typeof value === "number" && Number.isFinite(value) ? value : null;
}
export async function handleAiHordeImageGeneration({
model,
provider,
@@ -221,23 +212,19 @@ export async function handleAiHordeImageGeneration({
}
let completed = false;
let pollDelayMs = POLL_INTERVAL_MIN_MS;
try {
while (true) {
if (signal?.aborted) throw new Error("Horde image generation cancelled");
if (Date.now() >= deadline) {
throw Object.assign(new Error("Horde image generation timed out"), { status: 504 });
}
await sleep(pollDelayMs);
const checkRes = await safeOutboundFetch(
`${AI_HORDE_API_BASE}/v2/generate/check/${jobId}`,
{
headers: hordeHeaders(apiKey),
signal: signal ?? undefined,
guard: "none",
timeoutMs: boundedTimeoutMs(deadline, HORDE_API_CALL_TIMEOUT_MS),
}
);
await sleep(POLL_INTERVAL_MS);
const checkRes = await safeOutboundFetch(`${AI_HORDE_API_BASE}/v2/generate/check/${jobId}`, {
headers: hordeHeaders(apiKey),
signal: signal ?? undefined,
guard: "none",
timeoutMs: boundedTimeoutMs(deadline, HORDE_API_CALL_TIMEOUT_MS),
});
const check = await safeJson(checkRes);
if (!checkRes.ok || !check || typeof check !== "object") {
throw Object.assign(
@@ -252,55 +239,14 @@ export async function handleAiHordeImageGeneration({
status: 503,
});
}
if (!checkObj.done) {
// Horde сообщает оценку ожидания в первом же ответе. Если она не
// помещается в остаток бюджета, ждать нечего: запрос всё равно
// упал бы по таймауту, только молча и десятью минутами позже.
// Отказ называет очередь и число воркеров — по ним видно, что
// выручает не терпение, а модель с большим числом воркеров.
const waitSeconds = numericField(checkObj.wait_time);
const remainingMs = deadline - Date.now();
if (waitSeconds !== null && waitSeconds * 1_000 > remainingMs) {
const queuePosition = numericField(checkObj.queue_position);
const workers = numericField(checkObj.eligible_workers);
const details = [
`queue wait ~${Math.round(waitSeconds)}s`,
queuePosition !== null ? `position ${queuePosition}` : null,
workers !== null ? `${workers} eligible worker(s)` : null,
`budget ${Math.round(remainingMs / 1_000)}s left`,
]
.filter(Boolean)
.join(", ");
throw Object.assign(
new Error(
`Horde queue is longer than the request budget (${details}). ` +
`Pick a model with more workers or raise the timeout.`
),
{ status: 504 }
);
}
// Разрядка опроса: десятая доля оставшегося ожидания, в рамках
// минимума и максимума. Короткая очередь по-прежнему опрашивается
// раз в секунду.
pollDelayMs =
waitSeconds === null
? POLL_INTERVAL_MIN_MS
: Math.min(
POLL_INTERVAL_MAX_MS,
Math.max(POLL_INTERVAL_MIN_MS, Math.round((waitSeconds * 1_000) / 10))
);
continue;
}
if (!checkObj.done) continue;
const statusRes = await safeOutboundFetch(
`${AI_HORDE_API_BASE}/v2/generate/status/${jobId}`,
{
headers: hordeHeaders(apiKey),
signal: signal ?? undefined,
guard: "none",
timeoutMs: boundedTimeoutMs(deadline, HORDE_API_CALL_TIMEOUT_MS),
}
);
const statusRes = await safeOutboundFetch(`${AI_HORDE_API_BASE}/v2/generate/status/${jobId}`, {
headers: hordeHeaders(apiKey),
signal: signal ?? undefined,
guard: "none",
timeoutMs: boundedTimeoutMs(deadline, HORDE_API_CALL_TIMEOUT_MS),
});
const status = await safeJson(statusRes);
if (!statusRes.ok || !status || typeof status !== "object") {
throw Object.assign(

View File

@@ -11,27 +11,9 @@
import { saveCallLog } from "@/lib/usageDb";
import { sanitizeErrorMessage } from "../../utils/error.ts";
import { formatSearchProviderFailure } from "./providerFailure.ts";
import { HTTP_STATUS } from "../../config/constants.ts";
import { isSubscriptionQuotaText } from "../../services/quotaTextCooldowns.ts";
import type { SearchProviderConfig } from "../../config/searchRegistry.ts";
import type { SearchResult } from "../search.ts";
const SEARCH_COOLDOWN_STATUSES = new Set([
HTTP_STATUS.PAYMENT_REQUIRED,
HTTP_STATUS.REQUEST_TIMEOUT,
HTTP_STATUS.RATE_LIMITED,
HTTP_STATUS.PLAN_LIMIT_EXCEEDED,
HTTP_STATUS.SERVER_ERROR,
HTTP_STATUS.BAD_GATEWAY,
HTTP_STATUS.SERVICE_UNAVAILABLE,
HTTP_STATUS.GATEWAY_TIMEOUT,
]);
export function shouldCoolDownSearchConnection(status: number, errorText: string): boolean {
if (SEARCH_COOLDOWN_STATUSES.has(status)) return true;
return isSubscriptionQuotaText(errorText.toLowerCase());
}
/** Resolved proxy binding for a single provider attempt. */
export interface ResolvedSearchProxy {
proxy: unknown;
@@ -214,14 +196,6 @@ export async function executeProviderFetch(
if (log) {
log.error("SEARCH", `${config.id} error ${response.status}: ${errorText.slice(0, 200)}`);
}
if (connectionId && shouldCoolDownSearchConnection(response.status, errorText)) {
try {
const { markAccountUnavailable } = await import("@/sse/services/auth.ts");
await markAccountUnavailable(connectionId, response.status, errorText, config.id, null);
} catch {
/* non-critical - background cooldown mark must not break search response */
}
}
logCall({
status: response.status,
duration: Date.now() - startTime,

View File

@@ -35,11 +35,6 @@ function resolveVideoEndpoint(credentials: unknown, fallback: string): string {
? creds.baseUrl.trim()
: null;
const nodeBaseUrl = psdBaseUrl || topLevelBaseUrl;
// Узел своего адреса может не иметь — у встроенных провайдеров его и не
// бывает. Тогда работает `fallback`: это готовый endpoint из реестра, а не
// корень, поэтому путь к нему не дописывается (у nanogpt адрес оканчивается
// на /video/generations — в единственном числе).
if (!nodeBaseUrl) return fallback;
let n = nodeBaseUrl;
while (n.endsWith("/")) n = n.slice(0, -1);
if (n.endsWith("/videos/generations")) return n;

View File

@@ -1,16 +1,17 @@
/**
* Regression tests for the proxy-leak fix in grokTlsClient.
*
* Bug context (#3180): tlsFetchGrok() built its native tls-client-node
* requestOptions without a `proxyUrl` field, so every grok-web call
* Bug context (#3180): tlsFetchGrok() built its native transport options
* without a `proxyUrl` field, so every grok-web call
* egressed with the bare host IP regardless of the dashboard proxy config
* or HTTP_PROXY / HTTPS_PROXY env vars (the koffi-loaded Go binary does not
* consult Go's `http.ProxyFromEnvironment`).
* or HTTP_PROXY / HTTPS_PROXY env vars. Native browser transports require the
* resolved proxy to be passed explicitly.
*
* These tests pin the resolution-order contract:
* 1. Per-call `options.proxyUrl` wins.
* 2. POSIX-standard HTTPS_PROXY / HTTP_PROXY / ALL_PROXY (and lowercase variants).
* 3. Otherwise undefined (no proxy).
* 2. Request-scoped dashboard/account proxy context.
* 3. POSIX-standard HTTPS_PROXY / HTTP_PROXY / ALL_PROXY (and lowercase variants).
* 4. Otherwise undefined (no proxy).
*
* They also pin that the resolved proxy is actually placed on the
* requestOptions object handed to the native binding — the original bug

View File

@@ -77,7 +77,6 @@ import {
buildSubscriptionQuotaFallback,
buildWeeklyQuotaFallback,
buildSessionQuotaFallback,
SUBSCRIPTION_QUOTA_COOLDOWN_MS,
} from "./quotaTextCooldowns.ts";
import { parseDayGranularityResetMs, shouldPreserveQuotaSignals } from "./quotaResetParsing.ts";
import { evictLockoutOverflow } from "./accountFallback/lockoutEviction.ts";
@@ -1561,7 +1560,7 @@ export function classifyError(
if (status === HTTP_STATUS.UNAUTHORIZED || status === HTTP_STATUS.FORBIDDEN) {
return RateLimitReason.AUTH_ERROR;
}
if (status === HTTP_STATUS.PAYMENT_REQUIRED || status === HTTP_STATUS.PLAN_LIMIT_EXCEEDED) {
if (status === HTTP_STATUS.PAYMENT_REQUIRED) {
return RateLimitReason.QUOTA_EXHAUSTED;
}
if (status === HTTP_STATUS.RATE_LIMITED) {
@@ -2132,24 +2131,6 @@ export function checkFallbackError(
return buildRetryableFallback(RateLimitReason.SERVER_ERROR);
}
// 432 -- plan limit reached (e.g. Tavily, Context7, and search upstreams)
if (status === HTTP_STATUS.PLAN_LIMIT_EXCEEDED) {
const subResult = buildSubscriptionQuotaFallback(
errorStr,
() => getUpstreamRetryHint()?.retryAfterMs ?? null,
parseRetryFromErrorText,
provider
);
if (subResult) return subResult;
const cooldownMs = getUpstreamRetryHint()?.retryAfterMs ?? SUBSCRIPTION_QUOTA_COOLDOWN_MS;
return {
shouldFallback: true,
cooldownMs,
baseCooldownMs: cooldownMs,
reason: RateLimitReason.QUOTA_EXHAUSTED,
};
}
// 400 — context overflow / malformed request / model access denied
if (status === HTTP_STATUS.BAD_REQUEST) {
// Check structured error codes first (more reliable, no false positives)

View File

@@ -2,8 +2,8 @@
* Browser-TLS-impersonating HTTP client for claude.ai.
*
* Thin re-export over the shared `tlsClientBase.ts` factory
* (`createTlsClientModule`). All provider-agnostic logic (sidecar lifecycle,
* streaming tail-file, proxy resolution, error classes, SSE detection) lives
* (`createTlsClientModule`). All provider-agnostic logic (wreq-js transport
* pooling, direct streaming, proxy resolution, deadlines, SSE detection) lives
* in the base module; this file supplies only Claude-specific config and
* preserves the original public export surface.
*/
@@ -24,13 +24,13 @@ const HARD_TIMEOUT_GRACE_MS =
export const tlsClientModule = createTlsClientModule({
providerName: "Claude",
tlsProfile: `chrome_${CLAUDE_TLS_BROWSER_MAJOR_VERSION}`,
emulationOs: "linux",
domain: "https://claude.ai",
tempDirPrefix: "cgpt-stream-",
tailFileVariant: "A",
streamEofPolicy: "include",
responseValidation: "sse",
exportCloudflareCheck: false,
exposeStreamingForTesting: true,
// Claude waits indefinitely for the first SSE byte (original 2-arg waitForContent).
// Claude allows the native/hard request deadline to bound a slow first SSE byte.
defaultTimeoutMs: DEFAULT_TIMEOUT_MS,
hardTimeoutGraceMs: HARD_TIMEOUT_GRACE_MS,
firstByteTimeoutMs: Number.POSITIVE_INFINITY,

View File

@@ -7,7 +7,7 @@
* 3. Waits for Turnstile challenge to appear
* 4. Waits for challenge to be solved (with retry)
* 5. Extracts cf_clearance cookie
* 6. Returns fresh cookie for tls-client-node
* 6. Returns a fresh cookie for the isolated wreq-js request
*/
import type { Browser, Page } from "playwright";

View File

@@ -2,8 +2,8 @@
* Browser-TLS-impersonating HTTP client for grok.com.
*
* Thin re-export over the shared `tlsClientBase.ts` factory
* (`createTlsClientModule`). All provider-agnostic logic (sidecar lifecycle,
* streaming tail-file, proxy resolution, error classes, Cloudflare challenge
* (`createTlsClientModule`). All provider-agnostic logic (wreq-js transport
* pooling, direct streaming, proxy resolution, deadlines, Cloudflare challenge
* detection) lives in the base module; this file supplies only Grok-specific
* config and preserves the original public export surface.
*/
@@ -22,9 +22,9 @@ const HARD_TIMEOUT_GRACE_MS =
export const tlsClientModule = createTlsClientModule({
providerName: "Grok",
tlsProfile: "chrome_146",
emulationOs: "linux",
domain: "https://grok.com",
tempDirPrefix: "grok-stream-",
tailFileVariant: "B1",
streamEofPolicy: "exclude",
responseValidation: "cf",
exportCloudflareCheck: true,
defaultTimeoutMs: DEFAULT_TIMEOUT_MS,

View File

@@ -2,8 +2,8 @@
* Browser-TLS-impersonating HTTP client for arena.ai.
*
* Thin re-export over the shared `tlsClientBase.ts` factory
* (`createTlsClientModule`). All provider-agnostic logic (sidecar lifecycle,
* streaming tail-file, proxy resolution, error classes, Cloudflare challenge
* (`createTlsClientModule`). All provider-agnostic logic (wreq-js transport
* pooling, direct streaming, proxy resolution, deadlines, Cloudflare challenge
* detection) lives in the base module; this file supplies only LMArena-specific
* config and preserves the original public export surface.
*/
@@ -20,11 +20,12 @@ const HARD_TIMEOUT_GRACE_MS = 10_000;
export const tlsClientModule = createTlsClientModule({
providerName: "LMArena",
tlsProfile: "chrome_146",
emulationOs: "windows",
domain: "https://lmarena.ai",
// LMArena's proxy resolution domain is hardcoded to arena.ai, not the config domain.
proxyDomainOverride: "https://arena.ai",
tempDirPrefix: "LMArena-stream-",
tailFileVariant: "B2",
streamEofPolicy: "none",
streamEofSymbol: "",
responseValidation: "cf",
exportCloudflareCheck: true,
defaultTimeoutMs: DEFAULT_TIMEOUT_MS,

View File

@@ -2,8 +2,8 @@
* Browser-TLS-impersonating HTTP client for app.notion.com.
*
* Thin re-export over the shared `tlsClientBase.ts` factory
* (`createTlsClientModule`). All provider-agnostic logic (sidecar lifecycle,
* streaming tail-file, proxy resolution, error classes, SSE detection,
* (`createTlsClientModule`). All provider-agnostic logic (wreq-js transport
* pooling, direct streaming, proxy resolution, deadlines, SSE detection,
* Cloudflare challenge detection) lives in the base module; this file supplies
* only Notion-specific config and preserves the original public export surface.
*/
@@ -22,9 +22,9 @@ const HARD_TIMEOUT_GRACE_MS =
export const tlsClientModule = createTlsClientModule({
providerName: "Notion",
tlsProfile: "chrome_146",
emulationOs: "windows",
domain: "https://app.notion.com",
tempDirPrefix: "pplx-stream-",
tailFileVariant: "A",
streamEofPolicy: "include",
responseValidation: "sse",
exportCloudflareCheck: true,
defaultTimeoutMs: DEFAULT_TIMEOUT_MS,

View File

@@ -2,8 +2,8 @@
* Browser-TLS-impersonating HTTP client for www.perplexity.ai.
*
* Thin re-export over the shared `tlsClientBase.ts` factory
* (`createTlsClientModule`). All provider-agnostic logic (sidecar lifecycle,
* streaming tail-file, proxy resolution, error classes, SSE detection,
* (`createTlsClientModule`). All provider-agnostic logic (wreq-js transport
* pooling, direct streaming, proxy resolution, deadlines, SSE detection,
* Cloudflare challenge detection) lives in the base module; this file supplies
* only Perplexity-specific config and preserves the original public export
* surface.
@@ -23,9 +23,9 @@ const HARD_TIMEOUT_GRACE_MS =
export const tlsClientModule = createTlsClientModule({
providerName: "Perplexity",
tlsProfile: "firefox_148",
emulationOs: "macos",
domain: "https://www.perplexity.ai",
tempDirPrefix: "pplx-stream-",
tailFileVariant: "A",
streamEofPolicy: "include",
responseValidation: "sse",
exportCloudflareCheck: true,
defaultTimeoutMs: DEFAULT_TIMEOUT_MS,

View File

@@ -36,11 +36,6 @@ export function isSubscriptionQuotaText(lower: string, provider?: string | null)
lower.includes("claude pro usage limit") ||
lower.includes("you've reached your usage limit") ||
lower.includes("you have reached your usage limit") ||
lower.includes("exceeds your plan") ||
lower.includes("plan limit") ||
lower.includes("plan's set usage limit") ||
lower.includes("plan limit exceeded") ||
lower.includes("usage limit exceeded") ||
// Native Claude OAuth uses this otherwise-generic 429 wording for an
// exhausted subscription window. Keep it provider-scoped: other upstreams
// can use the same phrase for a short RPM throttle.
@@ -48,7 +43,7 @@ export function isSubscriptionQuotaText(lower: string, provider?: string | null)
);
}
export const SUBSCRIPTION_QUOTA_COOLDOWN_MS = 60 * 60 * 1000; // 1 hour
const SUBSCRIPTION_QUOTA_COOLDOWN_MS = 60 * 60 * 1000; // 1 hour
/**
* Builds the QUOTA_EXHAUSTED fallback for the subscription-quota text above.

File diff suppressed because it is too large Load Diff

View File

@@ -1,23 +0,0 @@
import { join } from "node:path";
import { resolveDataDir } from "@/lib/dataPaths";
/**
* Writable cache directory for tls-client-node's native binary.
*
* Without an explicit `downloadDir`, the library defaults to its own package
* `node_modules/tls-client-node/bin`, which is root-owned on global installs
* and fails with EACCES for normal users (#8579).
*/
export function resolveTlsClientDownloadDir(): string {
return join(resolveDataDir(), "tls-client", "bin");
}
export function buildNativeTlsClientOptions(): {
runtimeMode: "native";
downloadDir: string;
} {
return {
runtimeMode: "native",
downloadDir: resolveTlsClientDownloadDir(),
};
}

View File

@@ -156,18 +156,12 @@ function normalizeProviderPrefix(
* @param aliasToCanonical - When provided, the inner provider prefix of each variant id is
* normalized to its canonical form (e.g. "cc" → "claude"). Pass this when the catalog is
* emitting canonical-prefixed ids so no-think variants stay consistent with the prefix mode.
* @param options.featureEnabled - `false` returns the models untouched (feature flag off).
*/
export function appendNoThinkingVariants<T extends CatalogModelEntry>(
models: T[],
aliasToCanonical?: Record<string, string>,
options?: { featureEnabled?: boolean }
aliasToCanonical?: Record<string, string>
): T[] {
if (!Array.isArray(models)) return models;
// #11971: the catalog passes the DISABLE_THINKING_LEVEL_VARIANTS feature flag here; when
// the alias feature is switched off no variant is appended (the call site typed this
// third argument before it existed — TS2554 on the release tip).
if (options?.featureEnabled === false) return models;
const variants: T[] = [];
for (const model of models) {
if (!shouldExposeNoThinkingAlias(model)) continue;

177
package-lock.json generated
View File

@@ -165,8 +165,7 @@
"keytar": "^7.9.0",
"onnxruntime-node": "1.24.3",
"sqlite-vec": "^0.1.9",
"tls-client-node": "^0.2.0",
"wreq-js": "^3.1.0"
"wreq-js": "3.0.0"
}
},
"node_modules/@adobe/css-tools": {
@@ -13626,118 +13625,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/@wreq-js/binding-darwin-arm64": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@wreq-js/binding-darwin-arm64/-/binding-darwin-arm64-3.1.0.tgz",
"integrity": "sha512-wa9xns8VngAc6rOv9f8AtLQVb0NttBtbJpxeTZBLyWY/6+q+HjVBfV/0VwoYO8xCL+U+VwYWHn2X80LvL2nvVg==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@wreq-js/binding-darwin-x64": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@wreq-js/binding-darwin-x64/-/binding-darwin-x64-3.1.0.tgz",
"integrity": "sha512-93y4x2XBlLRBUhCnCDeOUkH54eCut1RIrIOkWmWBDDBjM1VyLq2SxGEprWoEV2JMNaavTbrMM589MqwlqFA18w==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@wreq-js/binding-linux-arm64-gnu": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@wreq-js/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-3.1.0.tgz",
"integrity": "sha512-98F2f95iMaFhfo6JuNXYpZRI8L0nK9h2/UOsaqN6CI7qUbAk/Cjf4FqYSIFs4FgC2Upe3Ju1ySxEXIWGXYPmeA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@wreq-js/binding-linux-arm64-musl": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@wreq-js/binding-linux-arm64-musl/-/binding-linux-arm64-musl-3.1.0.tgz",
"integrity": "sha512-FSjTGsj+Q/+wFWtGT7NwX7pRfaHRpKtcCq5WxviPei1+hpEX43EFHMfx0/taw2kDdArQ381MhVyrBQmZ1r4p5w==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@wreq-js/binding-linux-x64-gnu": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@wreq-js/binding-linux-x64-gnu/-/binding-linux-x64-gnu-3.1.0.tgz",
"integrity": "sha512-+vNDkG6DtW/BAdzxfqycspHIsKYfS1EC21FoXUpgCfvEA5UZDTGE7funimEh+/T9WZmrH6ce9sjaWA2U32SIPA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@wreq-js/binding-linux-x64-musl": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@wreq-js/binding-linux-x64-musl/-/binding-linux-x64-musl-3.1.0.tgz",
"integrity": "sha512-PwS/8pNlyJZRxcUwYOAGhUQg3nx3/zWeOItGDlpnJFFNs7ooTRipVE25hLebZbCH0a5pydkprqQDy+KL5vMRWg==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@wreq-js/binding-win32-x64-msvc": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@wreq-js/binding-win32-x64-msvc/-/binding-win32-x64-msvc-3.1.0.tgz",
"integrity": "sha512-rIhGDdsgtYdf9qSJvSU19Lu1yVa+6PTSjFE0SifUcimAP5cLJVysRyt8imxzv8c6+eGoEwqApvZ4SgBbED+3aQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@xmldom/xmldom": {
"version": "0.9.10",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.10.tgz",
@@ -25448,17 +25335,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/koffi": {
"version": "2.16.1",
"resolved": "https://registry.npmjs.org/koffi/-/koffi-2.16.1.tgz",
"integrity": "sha512-0Ie6CfD026dNfWSosDw9dPxPzO9Rlyo0N8m5r05S8YjytIpuilzMFDMY4IDy/8xQsTwpuVinhncD+S8n3bcYZQ==",
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"funding": {
"url": "https://liberapay.com/Koromix"
}
},
"node_modules/kuler": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
@@ -25648,17 +25524,6 @@
"node": ">= 14"
}
},
"node_modules/libxmljs2/node_modules/brace-expansion": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz",
"integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/libxmljs2/node_modules/cacache": {
"version": "19.0.1",
"resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz",
@@ -35722,7 +35587,7 @@
"version": "7.0.27",
"resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.27.tgz",
"integrity": "sha512-I4FZcVFcqCRuT0ph6dCDpPuO4Xgzvh+spkcTr1gK7peIvxWauoloVO0vuy1FQnijT63ss6AsHB6+OIM4aXHbPg==",
"devOptional": true,
"dev": true,
"license": "MIT",
"dependencies": {
"tldts-core": "^7.0.27"
@@ -35735,28 +35600,9 @@
"version": "7.0.27",
"resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.27.tgz",
"integrity": "sha512-YQ7uPjgWUibIK6DW5lrKujGwUKhLevU4hcGbP5O6TcIUb+oTjJYJVWPS4nZsIHrEEEG6myk/oqAJUEQmpZrHsg==",
"devOptional": true,
"dev": true,
"license": "MIT"
},
"node_modules/tls-client-node": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/tls-client-node/-/tls-client-node-0.2.0.tgz",
"integrity": "sha512-0PHJgaGPvMK9ly7xohviOoe8Oxos43IOIdsEhibgku4ce/3/YLhxJTPPKNQZII0PdcOjlfPweB9eRs13mWaWIg==",
"hasInstallScript": true,
"license": "SEE LICENSE IN LICENSE",
"optional": true,
"dependencies": {
"koffi": "^2.8.9",
"tough-cookie": "^6.0.1"
},
"engines": {
"node": ">=18.17"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/fatihkabakk"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -35815,7 +35661,7 @@
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.2.tgz",
"integrity": "sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==",
"devOptional": true,
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"tldts": "^7.0.5"
@@ -37730,9 +37576,9 @@
"license": "ISC"
},
"node_modules/wreq-js": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/wreq-js/-/wreq-js-3.1.0.tgz",
"integrity": "sha512-c+DF8s0kiCwTzXFwCNjBYJZMkodk2OukamoielaPegXWctrDth5tB1w0mszX7nysIJU4zge5q0RZUfoOfqH+uQ==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/wreq-js/-/wreq-js-3.0.0.tgz",
"integrity": "sha512-RZCoRSevVPpH4A4B4MxbFGo/pVPFveWd2gbe4ENKpPWlKXEYklZSDESOjBMmrIsmnkHh+nhM4PNJvG+NL7wBPA==",
"cpu": [
"x64",
"arm64"
@@ -37746,15 +37592,6 @@
],
"engines": {
"node": ">=20.0.0"
},
"optionalDependencies": {
"@wreq-js/binding-darwin-arm64": "3.1.0",
"@wreq-js/binding-darwin-x64": "3.1.0",
"@wreq-js/binding-linux-arm64-gnu": "3.1.0",
"@wreq-js/binding-linux-arm64-musl": "3.1.0",
"@wreq-js/binding-linux-x64-gnu": "3.1.0",
"@wreq-js/binding-linux-x64-musl": "3.1.0",
"@wreq-js/binding-win32-x64-msvc": "3.1.0"
}
},
"node_modules/write-file-atomic": {

View File

@@ -1,7 +1,7 @@
{
"name": "omniroute",
"version": "3.8.51",
"description": "Unified AI router with 352 providers, RTK+Caveman compression, auto fallback, MCP/A2A, desktop, PWA, and OpenAI-compatible APIs.",
"description": "Unified AI router with 351 providers, RTK+Caveman compression, auto fallback, MCP/A2A, desktop, PWA, and OpenAI-compatible APIs.",
"type": "module",
"bin": {
"omniroute": "bin/omniroute.mjs",
@@ -22,7 +22,6 @@
"src/types/",
".env.example",
"scripts/build/postinstall.mjs",
"scripts/build/fixTlsClientNodeBinary.mjs",
"scripts/build/fixPlaywrightAndroid.mjs",
"bin/cli/runtime/",
"scripts/postinstall.mjs",
@@ -38,6 +37,8 @@
"scripts/build/backendOnlyPages.mjs",
"scripts/build/build-tproxy-native.mjs",
"scripts/build/native-binary-compat.mjs",
"scripts/build/wreqJsNative.mjs",
"config/release/wreq-js-native-manifest.json",
"scripts/build/build-next-isolated.mjs",
"scripts/build/runtime-env.mjs",
"scripts/packs/optionalPackManifest.mjs",
@@ -356,8 +357,7 @@
"keytar": "^7.9.0",
"onnxruntime-node": "1.24.3",
"sqlite-vec": "^0.1.9",
"tls-client-node": "^0.2.0",
"wreq-js": "^3.1.0"
"wreq-js": "3.0.0"
},
"devDependencies": {
"@axe-core/playwright": "^4.13.0",

View File

@@ -12,12 +12,10 @@ allowBuilds:
core-js: true
esbuild: true
keytar: true
koffi: true
libxmljs2: true
onnxruntime-node: true
protobufjs: true
sharp: true
tls-client-node: true
unrs-resolver: true
onlyBuiltDependencies:
- "@parcel/watcher"
@@ -26,11 +24,9 @@ onlyBuiltDependencies:
- "core-js"
- "esbuild"
- "keytar"
- "koffi"
- "libxmljs2"
- "onnxruntime-node"
- "omniroute"
- "protobufjs"
- "sharp"
- "tls-client-node"
- "unrs-resolver"

View File

@@ -6,13 +6,11 @@
"core-js",
"esbuild",
"keytar",
"koffi",
"libxmljs2",
"omniroute",
"onnxruntime-node",
"protobufjs",
"sharp",
"tls-client-node",
"unrs-resolver"
]
}

View File

@@ -1,148 +0,0 @@
#!/usr/bin/env node
/**
* tls-client-node postinstall repair (#7802).
*
* tls-client-node's own postinstall.js fetches a platform-specific native
* binary (.so/.dylib/.dll) from the bogdanfinn/tls-client GitHub Releases
* API. That script is blocked by `npm ci --ignore-scripts` (the Dockerfile
* builder stage runs with scripts disabled for supply-chain hygiene) and,
* even when it does run, silently no-ops on a rate-limited/failed GitHub API
* call instead of raising — so `node_modules/tls-client-node/bin/` can end
* up empty with no visible signal until the first live request throws
* TlsClientUnavailableError (claude-web/grok-web/lmarena/
* perplexity-web all share this transport).
*
* This module:
* 1. Copies an already-fetched root `bin/` into the standalone
* `dist/node_modules/tls-client-node/bin/` bundle (same pattern as
* fixWreqJsBinary), so the published npm package works even though its
* own `files` allowlist never ships the binary.
* 2. When the root `bin/` is empty (--ignore-scripts blocked it, or a
* transient GitHub rate-limit ate the first attempt), retries the
* module's own postinstall.js with exponential backoff instead of
* giving up on the first failure.
*
* Best-effort throughout: a failure here never throws out of postinstall.mjs
* — it only warns, matching the other fix*Binary() steps. The runtime layer
* (perplexityTlsClient.ts and its 4 siblings) already surfaces a clear
* TlsClientUnavailableError pointing at the missing binary, so an operator
* who hits a still-empty bin/ after this repair gets an actionable message
* rather than an opaque crash.
*/
import { copyFileSync, existsSync, mkdirSync, readdirSync } from "node:fs";
import { join } from "node:path";
const DEFAULT_RETRY_DELAYS_MS = [1_000, 3_000, 8_000];
function hasAnyFile(dir) {
if (!existsSync(dir)) return false;
try {
return readdirSync(dir).length > 0;
} catch {
return false;
}
}
function copyBinDir(sourceDir, destDir) {
mkdirSync(destDir, { recursive: true });
for (const file of readdirSync(sourceDir)) {
copyFileSync(join(sourceDir, file), join(destDir, file));
}
}
async function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
/**
* Re-run tls-client-node's own postinstall.js in-process, retrying with
* backoff when the attempt leaves `bin/` empty (covers transient GitHub API
* rate-limiting — the upstream script itself never throws on failure, it
* only warns, so "still empty after running it" is the only failure signal
* available).
*/
async function downloadWithRetry(rootTlsClientDir, retryDelaysMs, log) {
const postinstallScript = join(rootTlsClientDir, "scripts", "postinstall.js");
const binDir = join(rootTlsClientDir, "bin");
if (!existsSync(postinstallScript)) return false;
for (let attempt = 0; attempt <= retryDelaysMs.length; attempt++) {
if (attempt > 0) {
log(
` ⏳ tls-client-node native binary still missing — retrying download ` +
`(attempt ${attempt + 1}/${retryDelaysMs.length + 1}) after rate-limit/backoff...`
);
await sleep(retryDelaysMs[attempt - 1]);
}
try {
const { execFileSync } = await import("node:child_process");
execFileSync(process.execPath, [postinstallScript], {
cwd: rootTlsClientDir,
stdio: "pipe",
timeout: 30_000,
});
} catch (err) {
log(` ⚠️ tls-client-node postinstall attempt failed: ${err.message.split("\n")[0]}`);
}
if (hasAnyFile(binDir)) return true;
}
return false;
}
/**
* @param {object} opts
* @param {string} opts.rootDir - repo root
* @param {(msg: string) => void} [opts.log]
* @param {number[]} [opts.retryDelaysMs] - override for tests (avoid real sleeps)
*/
export async function fixTlsClientNodeBinary({
rootDir,
log = (m) => console.log(m),
retryDelaysMs = DEFAULT_RETRY_DELAYS_MS,
} = {}) {
const rootTlsClientDir = join(rootDir, "node_modules", "tls-client-node");
const rootBinDir = join(rootTlsClientDir, "bin");
const distTlsClientDir = join(rootDir, "dist", "node_modules", "tls-client-node");
if (!existsSync(rootTlsClientDir)) return;
if (!hasAnyFile(rootBinDir)) {
log(
"\n 🔧 tls-client-node native binary missing (blocked by --ignore-scripts or a " +
"failed fetch) — attempting repair...\n"
);
const recovered = await downloadWithRetry(rootTlsClientDir, retryDelaysMs, log);
if (!recovered) {
console.warn(
"\n ⚠️ Could not fetch tls-client-node's native binary " +
"(GitHub API rate-limited or unreachable after retries)."
);
console.warn(
" claude-web/grok-web/lmarena/perplexity-web will raise a clear " +
"TlsClientUnavailableError on first use until this is resolved."
);
console.warn(
` Manual fix: node ${join(rootTlsClientDir, "scripts", "postinstall.js")}\n`
);
return;
}
log(" ✅ tls-client-node native binary fetched successfully!\n");
}
if (!existsSync(distTlsClientDir) || !hasAnyFile(rootBinDir)) return;
const distBinDir = join(distTlsClientDir, "bin");
if (hasAnyFile(distBinDir)) return;
try {
copyBinDir(rootBinDir, distBinDir);
log(" ✅ tls-client-node native binary copied to standalone dist/node_modules.\n");
} catch (err) {
console.warn(` ⚠️ Could not copy tls-client-node binary into dist/: ${err.message}`);
}
}

View File

@@ -7,9 +7,9 @@
* matrix leg. Everything except install-machine-forked optional packages is
* platform-independent:
*
* - Bundled-for-all (verify only): koffi ships every triplet under
* `build/koffi/<os>_<arch>`, better-sqlite3 v13 ships Node-API prebuilds for
* 8 platforms, wreq-js ships `rust/wreq-js.<plat>-<arch>[-libc].node`, and
* - Bundled-for-all (verify only): better-sqlite3 v13 ships Node-API prebuilds
* for 8 platforms, wreq-js ships
* `rust/wreq-js.<plat>-<arch>[-libc].node`, and
* onnxruntime-node ships `bin/napi-v6/<os>/<arch>`.
* - Install-machine-forked (hydrate): `@img/sharp-*`, `@img/sharp-libvips-*`,
* `@ngrok/ngrok-*` and macOS-only `fsevents` resolve to whichever platform
@@ -33,8 +33,7 @@ export const HYDRATED_ROOT_PACKAGES = ["fsevents"];
export const BUNDLED_EXEMPTIONS = new Set(["onnxruntime-node:darwin-x64"]);
function platformTriple(platform, arch) {
// koffi uses underscore triplets; better-sqlite3/wreq-js/onnx use dashes.
return { koffi: `${platform}_${arch}`, dash: `${platform}-${arch}` };
return { dash: `${platform}-${arch}` };
}
function rmrf(target) {
@@ -106,9 +105,6 @@ export function verifyBundledNatives({ nodeModulesDir, platform, arch }) {
const errors = [];
const triple = platformTriple(platform, arch);
const koffiDir = path.join(nodeModulesDir, "koffi", "build", "koffi", triple.koffi);
if (!fs.existsSync(koffiDir)) errors.push(`koffi: missing bundled triplet ${triple.koffi}`);
const sqlitePrebuild = path.join(
nodeModulesDir,
"better-sqlite3",

View File

@@ -94,6 +94,7 @@ export const PACK_ARTIFACT_ROOT_ALLOWED_EXACT_PATHS: string[] = [
"LICENSE",
"README.md",
"THIRD_PARTY_NOTICES.md",
"config/release/wreq-js-native-manifest.json",
"bin/aliasResolver.mjs",
"bin/chatgpt-web-codex-mcp.mjs",
// #7808: ESM loader hook split out of bin/aliasResolver.mjs to silence CodeQL
@@ -136,12 +137,10 @@ export const PACK_ARTIFACT_ROOT_ALLOWED_EXACT_PATHS: string[] = [
"scripts/build/build-next-isolated.mjs",
"scripts/check/check-supported-node-runtime.ts",
"scripts/build/native-binary-compat.mjs",
"scripts/build/wreqJsNative.mjs",
"scripts/build/postinstall.mjs",
"scripts/build/postinstallSupport.mjs",
"scripts/build/colocateOptionals.mjs",
// #7802: imported by scripts/build/postinstall.mjs to repair tls-client-node's
// native binary (claude-web/grok-web/lmarena/perplexity-web transport).
"scripts/build/fixTlsClientNodeBinary.mjs",
// #8859: imported by scripts/build/postinstall.mjs to repair playwright-core's
// browser resolution on Termux/Android (no glibc, no bundled browsers).
"scripts/build/fixPlaywrightAndroid.mjs",
@@ -222,13 +221,14 @@ export const PACK_ARTIFACT_REQUIRED_PATHS: string[] = [
// or the CLI fails to boot — list them REQUIRED so a regression is loud.
"bin/aliasResolver.mjs",
"bin/aliasResolverHook.mjs",
"config/release/wreq-js-native-manifest.json",
"package.json",
"scripts/build/native-binary-compat.mjs",
"scripts/build/postinstall.mjs",
"scripts/build/postinstallSupport.mjs",
"scripts/build/colocateOptionals.mjs",
"scripts/build/fixTlsClientNodeBinary.mjs",
"scripts/build/runtime-env.mjs",
"scripts/build/wreqJsNative.mjs",
// #10382: runtime imports of bin/cli/commands/packs.mjs (optional packs CLI) —
// listed REQUIRED so their absence from the tarball fails loudly.
"scripts/packs/optionalPackInstaller.mjs",

View File

@@ -14,8 +14,7 @@
*
* Modules repaired:
* - better-sqlite3 (SQLite bindings)
* - wreq-js (TLS client for OAuth providers)
* - tls-client-node (TLS client for claude-web/grok-web/lmarena/perplexity-web)
* - wreq-js (TLS client for OAuth and web-cookie providers)
* - sql.js (WASM SQLite fallback runtime)
* - node-machine-id (local CLI machine-token server runtime)
*
@@ -26,15 +25,7 @@
* Fixes: https://github.com/diegosouzapw/OmniRoute/issues/7802
*/
import {
copyFileSync,
cpSync,
existsSync,
mkdirSync,
readFileSync,
readdirSync,
writeFileSync,
} from "node:fs";
import { copyFileSync, cpSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { createRequire } from "node:module";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
@@ -42,8 +33,8 @@ import { fileURLToPath } from "node:url";
import { PUBLISHED_BUILD_ARCH, PUBLISHED_BUILD_PLATFORM } from "./native-binary-compat.mjs";
import { hasStandaloneAppBundle, isTermux } from "./postinstallSupport.mjs";
import { colocateLlmlinguaOptionals } from "./colocateOptionals.mjs";
import { fixTlsClientNodeBinary } from "./fixTlsClientNodeBinary.mjs";
import { fixPlaywrightAndroid } from "./fixPlaywrightAndroid.mjs";
import { resolveWreqJsNativeBinaryName } from "./wreqJsNative.mjs";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
@@ -277,7 +268,7 @@ async function fixWreqJsBinary() {
if (process.platform === "android" || isTermux()) {
console.log(
" [postinstall] wreq-js: skipped on Termux/Android " +
"(libgcc not available — OAuth TLS fingerprinting will use the fallback path)"
"(wreq-js 3.0.0 does not publish an Android native addon)"
);
return;
}
@@ -289,7 +280,16 @@ async function fixWreqJsBinary() {
return;
}
const binaryName = `wreq-js.${process.platform}-${process.arch}.node`;
const binaryName = resolveWreqJsNativeBinaryName({
platform: process.platform,
arch: process.arch,
});
if (!binaryName) {
console.warn(
` ⚠️ wreq-js 3.0.0 has no native addon for ${process.platform}-${process.arch}.`
);
return;
}
const appBinaryPath = join(appWreqDir, binaryName);
const rootBinaryPath = join(rootWreqDir, binaryName);
@@ -318,27 +318,7 @@ async function fixWreqJsBinary() {
}
}
// Strategy 2: Copy entire rust/ directory from root (gets all platform binaries)
if (existsSync(rootWreqDir)) {
try {
mkdirSync(appWreqDir, { recursive: true });
const files = readdirSync(rootWreqDir);
for (const file of files) {
if (file.endsWith(".node")) {
copyFileSync(join(rootWreqDir, file), join(appWreqDir, file));
}
}
if (existsSync(appBinaryPath)) {
process.dlopen({ exports: {} }, appBinaryPath);
console.log(" ✅ wreq-js native module fixed (full copy) successfully!\n");
return;
}
} catch (err) {
console.warn(` ⚠️ wreq-js full copy failed: ${err.message}`);
}
}
// Strategy 3: Rebuild wreq-js inside dist/
// Strategy 2: Rebuild wreq-js inside dist/
console.log(" 📥 Attempting npm rebuild wreq-js...");
try {
const { execSync } = await import("node:child_process");
@@ -359,8 +339,10 @@ async function fixWreqJsBinary() {
console.warn(
`\n ⚠️ Could not fix wreq-js native module for ${process.platform}-${process.arch}.`
);
console.warn(" OAuth-based providers (Codex, Cursor, etc.) may not work.");
console.warn(` Manual fix: cd ${join(ROOT, "dist")} && npm install wreq-js --no-save\n`);
console.warn(" Browser-TLS OAuth and web-cookie providers may not work.");
console.warn(
` Manual fix: cd ${join(ROOT, "dist")} && npm install wreq-js@3.0.0 --save-exact\n`
);
}
async function ensureSwcHelpers() {
@@ -470,7 +452,6 @@ async function ensureStandaloneRuntimePackages() {
await verifyDevNativeModules();
await fixBetterSqliteBinary();
await fixWreqJsBinary();
await fixTlsClientNodeBinary({ rootDir: ROOT });
await fixPlaywrightAndroid({ rootDir: ROOT });
await ensureSwcHelpers();
await ensureStandaloneRuntimePackages();

Some files were not shown because too many files have changed in this diff Show More