Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
d1723b7
fix(providers): add alwaysReasons metadata for reka-flash-3 (#13198)
Sep 13, 2026
0c25f61
fix(playground): allow Compare columns to scroll independently (fixes…
Sep 13, 2026
f7dbfc8
chore(tests): revive 51 vitest files parked behind a closed tracker (…
diegosouzapw Sep 14, 2026
30bf6af
fix(nvidia): fail open when a synced model catalog goes stale (#12849…
diegosouzapw Sep 14, 2026
963d3c4
fix(ci): clear three base-reds on release/v3.8.51 — open-sse typechec…
diegosouzapw Sep 14, 2026
0d13ef4
feat(i18n): 8 new locales — Kannada, Malayalam, Odia, Punjabi, Nepali…
diegosouzapw Sep 14, 2026
8f36211
docs(i18n): sync provider and migration counts in the eight new llm.t…
diegosouzapw Sep 14, 2026
8786c17
fix(ci): clear the orphan base-reds on release/v3.8.51 — the #12867 p…
diegosouzapw Sep 14, 2026
895dda3
fix(ci): clear the base-reds on release/v3.8.51 — doc counts, catalog…
diegosouzapw Sep 14, 2026
5ca724d
fix(api): scope batch bulk-delete to the calling API key (#12969)
diegosouzapw Sep 14, 2026
67cb0ac
fix: chain serial quarantine step in npm test script (fixes #13286) (…
KooshaPari Sep 15, 2026
8bad85f
fix(logging): mask *-api-key headers in request-log pipeline (#13273)…
KooshaPari Sep 15, 2026
65f5131
fix(tests): correct stale Jina catalog prefix in custom-models test (…
KooshaPari Sep 15, 2026
04bea60
fix(backend): prune old backups after health-check-repair snapshots (…
KooshaPari Sep 15, 2026
43b2661
feat(mcp): carry context_length through MCP list_models_catalog proje…
KooshaPari Sep 15, 2026
2a6d058
fix: skip non-chat generation models in Test all models (#13409)
KooshaPari Sep 15, 2026
f938a08
fix(resilience): add CJK quota-exhaustion patterns to 429 classifier …
KooshaPari Sep 15, 2026
fdfa921
fix(backend): eval runner: failed calls no longer score as passed + d…
KooshaPari Sep 15, 2026
76c928d
fix(backend): eval runner opts out of output-style and memory injecti…
KooshaPari Sep 15, 2026
3a186c1
fix(dashboard): send provider in body for mini-playground web search …
KooshaPari Sep 15, 2026
38ce449
fix(providers): de-duplicate agy and antigravity model catalogs (#13410)
KooshaPari Sep 15, 2026
1738beb
fix(memory): merge memory into top-level system field instead of unsh…
KooshaPari Sep 15, 2026
fc111dc
feat(cli): make startup readiness budget configurable (#13369) (#13433)
KooshaPari Sep 15, 2026
222fe43
docs(providers): add Microsoft 365 Copilot (BizChat) provider guide (…
KooshaPari Sep 15, 2026
cce3a95
fix(tests): add DISABLE_IOREG_STRATEGY env var for macOS test compati…
KooshaPari Sep 15, 2026
97ae101
fix(combo): use traceId for call log id to prevent UNIQUE constraint …
KooshaPari Sep 15, 2026
bf66589
fix(auth): check model lockout before returning synthetic noauth conn…
KooshaPari Sep 15, 2026
c46ca1d
fix(compression): preserve instruction blocks from lossy engines (#13…
KooshaPari Sep 15, 2026
56fedf9
fix(compression): preserve polarity words and newlines in ultra heuri…
KooshaPari Sep 15, 2026
d4a1470
fix(compression): run user preservePatterns before built-in patterns …
KooshaPari Sep 15, 2026
918546a
fix(resilience): increase requestQueue.maxWaitMs default from 15s to …
KooshaPari Sep 15, 2026
fb3f298
fix(security): empty whitelist allows through to prevent admin lockou…
KooshaPari Sep 15, 2026
a0d8ad7
fix(antigravity): derive stable session ID from credentials for promp…
KooshaPari Sep 15, 2026
0b358db
fix(backend): guard memory_fts_au trigger with WHEN clause to stop FT…
KooshaPari Sep 15, 2026
d6e62ae
fix(free-tiers): remove obsolete Together $25 signup credit (#12526) …
KooshaPari Sep 15, 2026
cd112e3
chore(deps): pin csv-parse to ^7.0.2 via overrides (#13117) (#13300)
KooshaPari Sep 15, 2026
6a55d0a
chore(deps): bump hono from ^4.12.34 to ^4.13.7 (#13148) (#13301)
KooshaPari Sep 15, 2026
93a398f
chore(deps): pin joi to ^18.2.8 via overrides (#13085) (#13302)
KooshaPari Sep 15, 2026
30b5bf1
fix(guardrails): skip credential redaction for base64 image data URLs…
KooshaPari Sep 15, 2026
1cbb77c
fix(analytics): normalize provider aliases to canonical id in usage_h…
KooshaPari Sep 15, 2026
56ae80a
fix(reasoning): expand deepseek-v4 regex to match v4.1+ and add comma…
KooshaPari Sep 15, 2026
3b5ce24
fix(playground): allow Compare columns to scroll independently (#13532)
KooshaPari Sep 15, 2026
6ad3ffa
Merge release/v3.8.51 into #13531
diegosouzapw Sep 15, 2026
475ec8b
test(providers): reka-flash-3 gets the thinking-budget floor without …
diegosouzapw Sep 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 2 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2204,9 +2204,9 @@ APP_LOG_TO_FILE=true
# Also configurable from Dashboard > Settings > Feature Flags.
# OMNIROUTE_CONTROL_PLANE_PROXY_DIRECT_FALLBACK=false

# Rate limit maximum wait time before failing a request (ms). Default: 15000 (15s)
# Rate limit maximum wait time before failing a request (ms). Default: 30000 (30s)
# Used by: open-sse/services/rateLimitManager.ts
# RATE_LIMIT_MAX_WAIT_MS=15000
# RATE_LIMIT_MAX_WAIT_MS=30000

# Limiter-managed execution backstop (Bottleneck `expiration`): bounds a job's
# post-dispatch execution, never queue wait. Must stay ABOVE upstream
Expand Down
16 changes: 16 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ jobs:
- run: npm run check:test-discovery
- run: npm run check:radar-sentinels
- run: npm run check:tracked-artifacts
# A test parked in vitest.config.ts's exclude list does not run, and looks like
# coverage to whoever reads the tree. 62 files accumulated behind a comment pointing
# at #8618 — closed in August while the list grew to 62; 51 of them passed when
# finally measured (#13204). This gate requires every exclusion to name a tracker and
# to appear in config/quality/vitest-exclusions.json, so the debt stays reviewable.
- run: npm run check:vitest-exclusions
# (gap 30) Also lives in quality.yml's PR-only "Merge integrity" job — because the
# CHANGELOG half of that job needs a base to diff against. This half does NOT: the
# generator either reproduces the committed SKILL.md files or it does not.
Expand Down Expand Up @@ -515,6 +521,16 @@ jobs:
env:
BASE_REF: ${{ github.base_ref && format('origin/{0}', github.base_ref) || '' }}
run: node scripts/i18n/check-ui-value-drift.mjs
# Sibling of the drift gate above. That one catches an English value that was
# REWRITTEN; this one catches an English key that was ADDED while some locales never
# got it. The coverage gate at the top of this job cannot: it is a percentage per
# locale, and 11 absent keys out of ~13,000 leaves coverage at 99.9%. Incident: the
# Phase 3 canvas keys were translated across the 42 locales that existed, then the EU
# batch (#13044) took the repo to 51 and the nine newcomers shipped untranslated.
- name: i18n new-key coverage (a new key must reach every locale)
env:
BASE_REF: ${{ github.base_ref && format('origin/{0}', github.base_ref) || '' }}
run: node scripts/i18n/check-new-key-coverage.mjs

# #8038: cheap glossary/protected-terms consistency gate —
# complements i18n-ui-coverage (key parity) and the ICU `i18n` job below
Expand Down
5,586 changes: 3,233 additions & 2,353 deletions .i18n-state.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Repository map and Reference Documentation sections below.

## Project at a Glance

**OmniRoute** — unified AI proxy/router. One endpoint, 356 LLM providers, auto-fallback.
**OmniRoute** — unified AI proxy/router. One endpoint, 358 LLM providers, auto-fallback.

| Layer | Location | Purpose |
| ------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
Expand All @@ -56,7 +56,7 @@ Repository map and Reference Documentation sections below.
| Translators | `open-sse/translator/` | Format conversion (OpenAI↔Claude↔Gemini) |
| Transformer | `open-sse/transformer/` | Responses API ↔ Chat Completions |
| Services | `open-sse/services/` | Combo routing, rate limits, caching, etc |
| Database | `src/lib/db/` | SQLite domain modules (173 migrations) |
| Database | `src/lib/db/` | SQLite domain modules (175 migrations) |
| Domain/Policy | `src/domain/` | Policy engine, cost rules, fallback logic |
| MCP Server | `open-sse/mcp-server/` | 110 tools (45 canonical + memory/skill/GitHub/pool/gamification/plugin/Notion/Obsidian/local-corpus/RTK modules), 3 transports (stdio / SSE / Streamable HTTP), 33 scopes |
| A2A Server | `src/lib/a2a/` | JSON-RPC 2.0 agent protocol |
Expand Down
22 changes: 15 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@

</div>

> Stacking free tiers by hand is painful — dozens of SDKs, dozens of rate limits, and no idea how much you actually have. OmniRoute catalogs **444 free-tier entries across 34 recurring pool keys** and computes the token headline from the **16 pools with a published positive monthly budget plus five per-model Groq caps**, deduplicated by shared pool. Quotas that only open after a regional identity check (today: ModelScope) are shown apart, +~6M behind regional identity verification, and never summed into the headline. The result stays visible on the dashboard (`/dashboard/free-tiers`).
> Stacking free tiers by hand is painful — dozens of SDKs, dozens of rate limits, and no idea how much you actually have. OmniRoute catalogs **443 free-tier entries across 34 recurring pool keys** and computes the token headline from the **16 pools with a published positive monthly budget plus five per-model Groq caps**, deduplicated by shared pool. Quotas that only open after a regional identity check (today: ModelScope) are shown apart, +~6M behind regional identity verification, and never summed into the headline. The result stays visible on the dashboard (`/dashboard/free-tiers`).

<img src="./docs/diagrams/free-tier-budget.svg" width="100%" alt="OmniRoute free-tier budget card: ~1.47B free tokens per month steady, up to ~2.10B in the first month with signup credits, from 34 documented recurring pool keys covering 444 cataloged free-tier entries behind one endpoint. Honest pool-deduped math — each shared pool counted once, including 16 recurring pools with a published positive monthly token budget plus five per-model Groq caps; 13 providers are marked avoid in the terms-risk catalog so you decide. Budget bar includes Mistral 1B, Nara 210M, LLM7 150M, Groq 30M (five per-model caps) and smaller pools, plus first-month signup credits and permanently-free no-token-cap providers surfaced separately so they never inflate the headline. Live used/remaining on /dashboard/free-tiers."/>
<img src="./docs/diagrams/free-tier-budget.svg" width="100%" alt="OmniRoute free-tier budget card: ~1.47B free tokens per month steady, up to ~2.07B in the first month with signup credits, from 34 documented recurring pool keys covering 443 cataloged free-tier entries behind one endpoint. Honest pool-deduped math — each shared pool counted once, including 16 recurring pools with a published positive monthly token budget plus five per-model Groq caps; 13 providers are marked avoid in the terms-risk catalog so you decide. Budget bar includes Mistral 1B, Nara 210M, LLM7 150M, Groq 30M (five per-model caps) and smaller pools, plus first-month signup credits and permanently-free no-token-cap providers surfaced separately so they never inflate the headline. Live used/remaining on /dashboard/free-tiers."/>

> Animated summary of the live `/dashboard/free-tiers` page. Full methodology (pool dedupe, credit tiers, provider terms): **[docs/reference/FREE_TIERS.md](docs/reference/FREE_TIERS.md)**.
>
Expand Down Expand Up @@ -133,7 +133,7 @@
</div>

<div align="center">
<b>🌐 In 51 languages</b>
<b>🌐 In 59 languages</b>
<br/><br/>
<a href="README.md"><img src="docs/assets/flags/us.svg" width="30" alt="English (en)" title="English (en)"></a>
<a href="docs/i18n/pt-BR/README.md"><img src="docs/assets/flags/br.svg" width="30" alt="Português — Brasil (pt-BR)" title="Português — Brasil (pt-BR)"></a>
Expand Down Expand Up @@ -186,6 +186,14 @@
<a href="docs/i18n/sl/README.md"><img src="docs/assets/flags/si.svg" width="30" alt="Slovenščina (sl)" title="Slovenščina (sl)"></a>
<a href="docs/i18n/mt/README.md"><img src="docs/assets/flags/mt.svg" width="30" alt="Malti (mt)" title="Malti (mt)"></a>
<a href="docs/i18n/ga/README.md"><img src="docs/assets/flags/ie.svg" width="30" alt="Gaeilge (ga)" title="Gaeilge (ga)"></a>
<a href="docs/i18n/kn/README.md"><img src="docs/assets/flags/in.svg" width="30" alt="ಕನ್ನಡ (kn)" title="ಕನ್ನಡ (kn)"></a>
<a href="docs/i18n/ml/README.md"><img src="docs/assets/flags/in.svg" width="30" alt="മലയാളം (ml)" title="മലയാളം (ml)"></a>
<a href="docs/i18n/or/README.md"><img src="docs/assets/flags/in.svg" width="30" alt="ଓଡ଼ିଆ (or)" title="ଓଡ଼ିଆ (or)"></a>
<a href="docs/i18n/pa/README.md"><img src="docs/assets/flags/in.svg" width="30" alt="ਪੰਜਾਬੀ (pa)" title="ਪੰਜਾਬੀ (pa)"></a>
<a href="docs/i18n/ne/README.md"><img src="docs/assets/flags/np.svg" width="30" alt="नेपाली (ne)" title="नेपाली (ne)"></a>
<a href="docs/i18n/si/README.md"><img src="docs/assets/flags/lk.svg" width="30" alt="සිංහල (si)" title="සිංහල (si)"></a>
<a href="docs/i18n/my/README.md"><img src="docs/assets/flags/mm.svg" width="30" alt="မြန်မာ (my)" title="မြန်မာ (my)"></a>
<a href="docs/i18n/km/README.md"><img src="docs/assets/flags/kh.svg" width="30" alt="ខ្មែរ (km)" title="ខ្មែរ (km)"></a>
</div>

<br/>
Expand Down Expand Up @@ -529,7 +537,7 @@ Pix copia-e-cola:

The main free-tier headline remains **~1.47B tokens/month** from the documented,
pool-deduplicated catalog above. Temporary provider signup credits can separately lift the first
month to **~2.10B**. Radar is an optional, signed catalog overlay for people who want fresher
month to **~2.07B**. Radar is an optional, signed catalog overlay for people who want fresher
free-model availability between OmniRoute releases; the community catalog and every existing free
feature remain free.

Expand Down Expand Up @@ -657,7 +665,7 @@ of your shell history. → [CLI Integrations](docs/guides/CLI-INTEGRATIONS.md)

</div>

> **352 registered providers** across the canonical chat, media, search, local, cloud-agent and system collections, including **152 carrying `hasFree: true` discovery metadata**. The chat model registry covers **229 providers / 2,554 distinct provider-model pairs / 1,283 raw model IDs**; the separate free-budget catalog has **444 per-model rows**, **34 recurring pools** and **52 recurring/keyless free-forever providers**. These are different denominators by design; definitions and pool-deduped calculations live in the [Provider Reference](docs/reference/PROVIDER_REFERENCE.md) and [Free Tiers](docs/reference/FREE_TIERS.md).
> **352 registered providers** across the canonical chat, media, search, local, cloud-agent and system collections, including **152 carrying `hasFree: true` discovery metadata**. The chat model registry covers **229 providers / 2,554 distinct provider-model pairs / 1,283 raw model IDs**; the separate free-budget catalog has **443 per-model rows**, **34 recurring pools** and **52 recurring/keyless free-forever providers**. These are different denominators by design; definitions and pool-deduped calculations live in the [Provider Reference](docs/reference/PROVIDER_REFERENCE.md) and [Free Tiers](docs/reference/FREE_TIERS.md).

<div align="center">

Expand Down Expand Up @@ -1253,7 +1261,7 @@ Métricas canônicas em 2026-08-24: **1.029 vídeos únicos** · **11.132.922 vi
<tr><td nowrap><b>Runtime</b></td><td>Node.js 22.x / 24.x LTS — <code>&gt;=22.22.2 &lt;23 || &gt;=24.0.0 &lt;27</code></td></tr>
<tr><td nowrap><b>Language</b></td><td>TypeScript 6.0 — <b>100% TypeScript</b> across <code>src/</code> and <code>open-sse/</code> (zero <code>any</code> in core since v2.0)</td></tr>
<tr><td nowrap><b>Framework</b></td><td>Next.js 16 + React 19 + Tailwind CSS 4</td></tr>
<tr><td nowrap><b>Database</b></td><td>better-sqlite3 (SQLite, WAL journaling) + LowDB (JSON legacy) — 122 domain modules, 173 migrations</td></tr>
<tr><td nowrap><b>Database</b></td><td>better-sqlite3 (SQLite, WAL journaling) + LowDB (JSON legacy) — 122 domain modules, 175 migrations</td></tr>
<tr><td nowrap><b>Memory</b></td><td>SQLite FTS5 full-text + int8-quantized vector embeddings, typed decay</td></tr>
<tr><td nowrap><b>Schemas</b></td><td>Zod 4 — MCP tool I/O validation + API contracts</td></tr>
<tr><td nowrap><b>Protocols</b></td><td>MCP (stdio / HTTP / SSE) + A2A v0.3 (JSON-RPC 2.0 + SSE)</td></tr>
Expand Down Expand Up @@ -1316,7 +1324,7 @@ Métricas canônicas em 2026-08-24: **1.029 vídeos únicos** · **11.132.922 vi
<tr><td nowrap><b><a href="docs/architecture/RESILIENCE_GUIDE.md">Resilience Guide</a></b></td><td>Circuit breakers, cooldowns, queue, anti-thundering herd, TLS spoofing</td></tr>
<tr><td nowrap><b><a href="docs/routing/AUTO-COMBO.md">Auto-Combo Engine</a></b></td><td>16-factor scoring, mode packs, self-healing</td></tr>
<tr><td nowrap><b><a href="docs/ops/PROXY_GUIDE.md">Proxy Guide</a></b></td><td>3-level proxy system, 1proxy marketplace, registry CRUD</td></tr>
<tr><td nowrap><b><a href="docs/reference/FREE_TIERS.md">Free Tiers</a></b></td><td>Consolidated directory: 34 documented recurring pools / 444 cataloged free-tier entries</td></tr>
<tr><td nowrap><b><a href="docs/reference/FREE_TIERS.md">Free Tiers</a></b></td><td>Consolidated directory: 34 documented recurring pools / 443 cataloged free-tier entries</td></tr>
<tr><td nowrap><b><a href="docs/guides/FEATURES.md">Features Gallery</a></b></td><td>Visual dashboard tour with screenshots</td></tr>
<tr><td nowrap><b><a href="docs/architecture/CODEBASE_DOCUMENTATION.md">Codebase Documentation</a></b></td><td>Beginner-friendly codebase walkthrough</td></tr>
</table>
Expand Down
1 change: 1 addition & 0 deletions bin/cli/commands/env.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const OMNIROUTE_ENV_VARS = [
"OMNIROUTE_API_KEY",
"OMNIROUTE_BASE_URL",
"OMNIROUTE_HTTP_TIMEOUT_MS",
"OMNIROUTE_READY_TIMEOUT_MS",
];

const ENV_DEFAULTS = {
Expand Down
17 changes: 14 additions & 3 deletions bin/cli/commands/serve.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { join, dirname } from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
import { platform, totalmem } from "node:os";
import { t } from "../i18n.mjs";
import { writePidFile, cleanupPidFile, waitForServer } from "../utils/pid.mjs";
import { writePidFile, cleanupPidFile, waitForServer, resolveReadyTimeoutMs } from "../utils/pid.mjs";
import {
ServerSupervisor,
detectMitmCrash,
Expand Down Expand Up @@ -58,6 +58,11 @@ export function registerServe(program) {
.option("--max-restarts <n>", t("serve.max_restarts"), parseInt, 2)
.option("--tray", t("serve.tray") || "Start in the system tray (desktop only)")
.option("--no-tray", t("serve.no_tray") || "Disable system tray icon")
.option(
"--ready-timeout <ms>",
t("serve.ready_timeout") ||
"Readiness probe timeout in ms (also OMNIROUTE_READY_TIMEOUT_MS, default 60000)"
)
.option(
"--tls-cert <path>",
t("serve.tls_cert") ||
Expand Down Expand Up @@ -452,7 +457,8 @@ async function runWithSupervisor(
});

if (!showLog) {
waitForServer(dashboardPort, 60000).then(async (up) => {
const readyTimeoutMs = resolveReadyTimeoutMs({ timeoutMs: opts.readyTimeout });
waitForServer(dashboardPort, readyTimeoutMs).then(async (up) => {
if (up) {
if (useTray) {
const trayReady = await maybeStartTray(dashboardPort, apiPort, supervisor);
Expand Down Expand Up @@ -489,10 +495,15 @@ async function runWithSupervisor(
// reachable directly while the CLI still looks hung). Surface a clear diagnostic
// plus whatever stdout/stderr the child buffered instead of going silent.
export function reportReadinessTimeout(dashboardPort, supervisor) {
const readyTimeoutMs = resolveReadyTimeoutMs();
const seconds = Math.round(readyTimeoutMs / 1000);
console.error(
`\n\x1b[33m⚠ Server did not respond within 60s.\x1b[0m It may still be starting, or may` +
`\n\x1b[33m⚠ Server did not respond within ${seconds}s.\x1b[0m It may still be starting, or may` +
` have failed silently.`
);
console.error(
` Tip: set OMNIROUTE_READY_TIMEOUT_MS=${readyTimeoutMs * 2} or --ready-timeout ${readyTimeoutMs * 2} for slower cold starts.`
);
console.error(` Try: curl -I http://localhost:${dashboardPort}/api/monitoring/health`);
console.error(` Or: rerun with \x1b[36m--log\x1b[0m to see live server output.\n`);

Expand Down
Loading
Loading