mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-02 21:02:14 +03:00
Compare commits
147 Commits
chore/esli
...
docs/remov
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
abf8938fc2 | ||
|
|
53b037051b | ||
|
|
c420a51df6 | ||
|
|
d6412532c4 | ||
|
|
a25ac4d979 | ||
|
|
089e70cbc5 | ||
|
|
7c119dd7ed | ||
|
|
6da2418247 | ||
|
|
93fdc16e72 | ||
|
|
7802f6ea16 | ||
|
|
6d556c2422 | ||
|
|
9704195417 | ||
|
|
752aac65d6 | ||
|
|
2c6e6cd13e | ||
|
|
f41a9bd835 | ||
|
|
26d20a0009 | ||
|
|
990aeca1db | ||
|
|
0ec7504024 | ||
|
|
5a34111125 | ||
|
|
62e2481eef | ||
|
|
5a490b19e2 | ||
|
|
4f4aa74199 | ||
|
|
01d97beb8b | ||
|
|
70f33e323c | ||
|
|
8d16a50df5 | ||
|
|
3a5641839e | ||
|
|
c8e2cb3ffc | ||
|
|
bb5c6d148e | ||
|
|
eb09e894cb | ||
|
|
1146c9b5b5 | ||
|
|
674d39137d | ||
|
|
290f723ec0 | ||
|
|
393c305a71 | ||
|
|
d337c5d30d | ||
|
|
0389b07257 | ||
|
|
e7b1448281 | ||
|
|
8e474914ea | ||
|
|
090ae83e12 | ||
|
|
6a91002b39 | ||
|
|
530096a3be | ||
|
|
cabbbe410a | ||
|
|
382e2e85d2 | ||
|
|
6b4519c317 | ||
|
|
afb91a83bd | ||
|
|
c1ac943c70 | ||
|
|
e26a649d26 | ||
|
|
713440be0a | ||
|
|
a298dc6b73 | ||
|
|
451dd73870 | ||
|
|
9327990be6 | ||
|
|
af0a9609f4 | ||
|
|
24b784e9bb | ||
|
|
96824288f5 | ||
|
|
678e6077e4 | ||
|
|
5a0a131bc7 | ||
|
|
c702a27eda | ||
|
|
cf53b9220f | ||
|
|
d2a027a156 | ||
|
|
17a53d2eb9 | ||
|
|
7f25d67d07 | ||
|
|
1586476183 | ||
|
|
c9f9b6274e | ||
|
|
8ef3447950 | ||
|
|
a784b42060 | ||
|
|
a86b9019a8 | ||
|
|
438db55c46 | ||
|
|
6dd82b77de | ||
|
|
17792ce0ad | ||
|
|
5ff6513ca5 | ||
|
|
8fc6834372 | ||
|
|
ad4b67d631 | ||
|
|
5253b93b89 | ||
|
|
51587084ca | ||
|
|
bdf218387b | ||
|
|
3b82d85081 | ||
|
|
d19572fb95 | ||
|
|
5e6c9a92dc | ||
|
|
2f33f2c20d | ||
|
|
33bdc386bc | ||
|
|
78a0e4b109 | ||
|
|
accdfa9f33 | ||
|
|
9d04995950 | ||
|
|
abbbca216d | ||
|
|
fe5f4b0ef9 | ||
|
|
c818655b5a | ||
|
|
9629d78ece | ||
|
|
0ff164701d | ||
|
|
f301d34ce5 | ||
|
|
d920e6495a | ||
|
|
7f008ed09a | ||
|
|
e3c440e804 | ||
|
|
d898d1a913 | ||
|
|
ad54249c54 | ||
|
|
eeba382049 | ||
|
|
412298b624 | ||
|
|
f5e70950d3 | ||
|
|
073b98462d | ||
|
|
30a26d9dcb | ||
|
|
d53da4fdc8 | ||
|
|
3c8b553811 | ||
|
|
aa2aec5e59 | ||
|
|
6c93e74f26 | ||
|
|
2e17161ea2 | ||
|
|
5eaafe8e17 | ||
|
|
4bcd8cee99 | ||
|
|
7f9195cd29 | ||
|
|
06e7a6d50c | ||
|
|
9058e39b61 | ||
|
|
a249a9dc28 | ||
|
|
e7a65d28db | ||
|
|
05490304bf | ||
|
|
dc6daf27b6 | ||
|
|
903d1e0c52 | ||
|
|
8d388912a7 | ||
|
|
debb82bdd7 | ||
|
|
c49ee53bc1 | ||
|
|
0e5e195519 | ||
|
|
e0b9eb08e1 | ||
|
|
4d92ea9969 | ||
|
|
3383adbbd1 | ||
|
|
a4b4bca2ee | ||
|
|
18dd83cd87 | ||
|
|
ae37413aff | ||
|
|
26eeead268 | ||
|
|
1b64372316 | ||
|
|
ba200b8d2b | ||
|
|
978f32984c | ||
|
|
7ba5b7a74e | ||
|
|
2bd3023e09 | ||
|
|
d0529c0365 | ||
|
|
50a6f7e325 | ||
|
|
8acdd53025 | ||
|
|
ede327a613 | ||
|
|
ce1b142975 | ||
|
|
63e4afa321 | ||
|
|
7ca5e1c671 | ||
|
|
73db936f98 | ||
|
|
4b5266d3f8 | ||
|
|
f8b01c966e | ||
|
|
e12fb110f9 | ||
|
|
2fbd0f5c25 | ||
|
|
18c71b91dc | ||
|
|
9392bd55c2 | ||
|
|
90366903c4 | ||
|
|
668beed5b8 | ||
|
|
298ad0fd64 | ||
|
|
6706c382d8 |
51
.env.example
51
.env.example
@@ -240,7 +240,7 @@ PORT=20128
|
||||
# Used by: src/app/api/v1/relay/chat/completions/route.ts
|
||||
# RELAY_IP_PER_MINUTE=30
|
||||
|
||||
# Bundler selection for `npm run dev`. Set to 0 to fall back to webpack.
|
||||
# Bundler selection for `npm run dev` and `npm run build`. Set to 0 to fall back to webpack.
|
||||
# Default is 1 (Turbopack). PR #4092 had forced webpack because earlier
|
||||
# Turbopack 16.2.x panicked on the OmniRoute module graph with "internal error:
|
||||
# entered unreachable code: there must be a path to a root"
|
||||
@@ -250,8 +250,9 @@ PORT=20128
|
||||
# /api/v1/models, /api/mcp) and repeated HMR rebuilds: zero panics. Turbopack
|
||||
# also keeps dev memory far lower on the edit→rebuild loop (HMR rebuild RSS stays
|
||||
# ~flat vs webpack's monotonic growth), which mitigates the dev-server OOM on
|
||||
# this 60+ route app. The production build still uses webpack (build pipeline is
|
||||
# unaffected by this dev-only flag).
|
||||
# this 60+ route app. The production build (scripts/build/build-next-isolated.mjs)
|
||||
# reads the same flag: Turbopack by default, 0 builds with webpack (`npm run
|
||||
# build:contributor` sets it for you).
|
||||
OMNIROUTE_USE_TURBOPACK=1
|
||||
|
||||
# Disable systemd sd_notify (Type=notify / WatchdogSec=) even when running
|
||||
@@ -812,6 +813,7 @@ NEXT_PUBLIC_ENABLE_SOCKS5_PROXY=true
|
||||
# CLI_CRUSH_BIN=crush
|
||||
# CLI_OMP_BIN=omp
|
||||
# CLI_LETTA_BIN=letta
|
||||
# CLI_PRIME_AGENT_BIN=prime-agent
|
||||
# Windsurf has no default binary — set this to enable binary detection for it.
|
||||
# CLI_WINDSURF_BIN=windsurf
|
||||
# CLI_AUGGIE_BIN=auggie
|
||||
@@ -1150,11 +1152,6 @@ CODEX_OAUTH_CLIENT_ID=app_EMoamEEZ73f0CkXaXp7hrann
|
||||
# Trae OAuth token override. Used by: open-sse/executors/trae.ts.
|
||||
# TRAE_TOKEN=
|
||||
|
||||
# ── The Old LLM (theoldllm) ──
|
||||
# Playwright navigation timeout (ms) for the browser-backed token capture.
|
||||
# Used by: open-sse/executors/theoldllm.ts. Default: 30000 (30s).
|
||||
# THEOLDLLM_NAV_TIMEOUT_MS=30000
|
||||
|
||||
# ── Gemini / Antigravity (Google-based) ──
|
||||
# These providers ship public OAuth client_id/secret values embedded in their
|
||||
# public CLIs. Defaults are baked into the code via
|
||||
@@ -1828,7 +1825,7 @@ APP_LOG_TO_FILE=true
|
||||
# short alias prefix and the canonical provider prefix for each model (cc/claude-sonnet-4-6
|
||||
# AND claude/claude-sonnet-4-6) so client configs that hardcoded either form keep working —
|
||||
# which roughly doubles the catalog. "alias" emits one id per model; "canonical" emits only
|
||||
# the full provider-id prefix (and drops providers whose alias is already canonical).
|
||||
# the full provider-id prefix (providers whose alias is already canonical keep their one id).
|
||||
# A client can override per request with GET /v1/models?prefix=alias instead.
|
||||
# Also configurable from Dashboard > Settings > Feature Flags.
|
||||
# Used by: src/shared/constants/featureFlagDefinitions.ts, src/app/api/v1/models/catalog.ts
|
||||
@@ -2266,6 +2263,16 @@ APP_LOG_TO_FILE=true
|
||||
# Cursor image-generation wall clock (ms). Default: 210000.
|
||||
# CURSOR_IMG_TIMEOUT_MS=210000
|
||||
|
||||
# UC (uncensored.com) image-generation result-poll cadence + wall clock (ms).
|
||||
# Used by: open-sse/handlers/imageGeneration/providers/ucImage.ts. Defaults: 2000 / 60000.
|
||||
# UC_IMAGE_POLL_INTERVAL_MS=2000
|
||||
# UC_IMAGE_POLL_TIMEOUT_MS=60000
|
||||
|
||||
# UC (uncensored.com) video-generation result-poll cadence + wall clock (ms).
|
||||
# Used by: open-sse/handlers/videoGeneration/providers/ucVideo.ts. Defaults: 3000 / 300000.
|
||||
# UC_VIDEO_POLL_INTERVAL_MS=3000
|
||||
# UC_VIDEO_POLL_TIMEOUT_MS=300000
|
||||
|
||||
# Shared-seat concurrency gate for Cursor image jobs. Default: 2.
|
||||
# CURSOR_IMG_MAX_CONCURRENT=2
|
||||
|
||||
@@ -2397,6 +2404,9 @@ APP_LOG_TO_FILE=true
|
||||
# Bundled Codeium/language-server extension_version, distinct from Desktop.
|
||||
# Must use x.y.z format; invalid/unset values use the bundled default 1.48.2.
|
||||
# DEVIN_DESKTOP_EXTENSION_VERSION=1.48.2
|
||||
# Optional override for the Codeium seat-management API used by Devin CLI quota.
|
||||
# Used by: open-sse/services/usage/devinCli.ts. Default: https://server.codeium.com
|
||||
# DEVIN_SEAT_API_URL=https://server.codeium.com
|
||||
|
||||
# ── Command Code (custom CLI) callback ──
|
||||
# Local port used for OAuth-style callbacks from the Command Code CLI helper.
|
||||
@@ -2466,14 +2476,6 @@ APP_LOG_TO_FILE=true
|
||||
# When enabled, the node authenticates with the API key stored on its connection.
|
||||
# AUDIO_REMOTE_PROVIDER_NODES=false
|
||||
|
||||
# ── 1Proxy egress pool ──
|
||||
# Used by: src/lib/oneproxySync.ts — fetches proxy nodes from the OmniRoute
|
||||
# CrofAI 1Proxy service. Disable, override URL, or tune the import quality.
|
||||
# ONEPROXY_ENABLED=true
|
||||
# ONEPROXY_API_URL=https://1proxy-api.aitradepulse.com
|
||||
# ONEPROXY_MAX_PROXIES=500
|
||||
# ONEPROXY_MIN_QUALITY_THRESHOLD=50
|
||||
|
||||
# ── Free Proxy Pool (auto-sync scheduler) ──
|
||||
# Background refresh of the free-proxy pool. Opt-in, OFF by default (parallels
|
||||
# Hard Rule #20's default-off posture for data-mutating background features).
|
||||
@@ -2892,6 +2894,14 @@ QUOTA_STORE_DRIVER=sqlite
|
||||
# PROMPTQL_TOKEN_REFRESH_URL=https://auth.pro.ql.app/ddn/project/token
|
||||
# PROMPTQL_POLL_TIMEOUT_MS=180000
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Kilo Code usage quotas (src/shared/constants/providers/kilocode.ts)
|
||||
# Personal USD balance and Kilo Pass usage lookup. Optional — the default
|
||||
# points at the public Kilo API; override only for a relay/test fixture.
|
||||
# Authentication uses the connection's existing OAuth access token.
|
||||
# Used by: open-sse/services/usage/kilocode.ts
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# KILO_API_URL=https://api.kilo.ai
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# HyperAgent web provider (Unofficial/Experimental — src/shared/constants/providers/web-cookie.ts)
|
||||
# Reverse-engineered session bridge for hyperagent.com. Optional — defaults
|
||||
@@ -2911,7 +2921,12 @@ QUOTA_STORE_DRIVER=sqlite
|
||||
# CHATGPT_WEB_CODEX_CDP_URL=http://chatgpt-web-codex-browser:9223
|
||||
# CHATGPT_WEB_CODEX_TUNNEL_ID=tunnel_0123456789abcdef0123456789abcdef
|
||||
# CHATGPT_WEB_CODEX_RUNTIME_KEY=
|
||||
# CHATGPT_WEB_CODEX_CONNECTOR_NAME=OmniRoute Codex
|
||||
# CHATGPT_WEB_CODEX_CONNECTOR_NAME=OmniRoute Codex v2
|
||||
# CODEX_CHATGPT_WEB_HOME=/var/lib/omniroute/chatgpt-web-codex
|
||||
# CODEX_CHATGPT_WEB_BROWSER_DIAGNOSTICS=0
|
||||
# CODEX_CHATGPT_WEB_LAUNCHER=/absolute/path/to/codex-chatgpt-web
|
||||
# CODEX_CHATGPT_WEB_BUN=/absolute/path/to/bun
|
||||
# CODEX_WEB_GPT_BUN=/absolute/path/to/bun
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Browser-login VNC sessions (optional — src/lib/vncSession/manifest.ts)
|
||||
|
||||
48
.github/actions/npm-ci-retry/action.yml
vendored
48
.github/actions/npm-ci-retry/action.yml
vendored
@@ -1,9 +1,45 @@
|
||||
name: npm ci with retry
|
||||
description: Run npm ci with retries for transient registry/network failures.
|
||||
description: >-
|
||||
Install dependencies. Restores node_modules from the Actions cache when the exact
|
||||
lockfile / runner / Node version / postinstall inputs match; otherwise runs npm ci
|
||||
with retries for transient registry/network failures and saves the tree for the
|
||||
next run.
|
||||
inputs:
|
||||
cache:
|
||||
description: Set to "false" to skip the node_modules cache and always run npm ci.
|
||||
required: false
|
||||
default: "true"
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- shell: bash
|
||||
- name: Resolve Node version for the cache key
|
||||
id: node
|
||||
shell: bash
|
||||
run: echo "version=$(node --version)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# #8084 D3 (plan 3.8.51 task 5): every job used to pay ~80-90 s of `npm ci` even
|
||||
# with setup-node's npm tarball cache warm — 36 jobs per ci.yml run, ~55 min of
|
||||
# runner time per run just installing. A node_modules cache keyed on EVERYTHING
|
||||
# that shapes the tree lets a hit skip the install entirely.
|
||||
#
|
||||
# No restore-keys on purpose (same rule as the ESLint cache, #11600): a partial
|
||||
# tree from another lockfile / Node / postinstall script is exactly the kind of
|
||||
# silent drift a lockfile-pinned CI must never inherit. Exact key or a full npm ci.
|
||||
#
|
||||
# postinstall (scripts/build/postinstall.mjs + helpers) only mutates node_modules
|
||||
# on a plain install — its dist/ branch is gated on dist/ existing, which never
|
||||
# holds at install time in CI — so the cached tree already carries its effects.
|
||||
- name: Restore node_modules
|
||||
id: node-modules
|
||||
if: inputs.cache == 'true'
|
||||
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: node_modules
|
||||
key: node-modules-${{ runner.os }}-${{ runner.arch }}-${{ steps.node.outputs.version }}-${{ hashFiles('package-lock.json', '.npmrc', 'scripts/build/postinstall.mjs', 'scripts/build/postinstallSupport.mjs', 'scripts/build/colocateOptionals.mjs', 'scripts/build/fixTlsClientNodeBinary.mjs', 'scripts/build/fixPlaywrightAndroid.mjs', 'scripts/build/native-binary-compat.mjs') }}
|
||||
|
||||
- name: npm ci (with retry)
|
||||
if: steps.node-modules.outputs.cache-hit != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
@@ -15,7 +51,8 @@ runs:
|
||||
echo "npm ci attempt $attempt/$max_attempts after transient failure"
|
||||
fi
|
||||
|
||||
if npm ci; then
|
||||
# --no-audit: `audit:deps` is its own gate; the inline audit only adds latency.
|
||||
if npm ci --no-audit --no-fund; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -27,3 +64,8 @@ runs:
|
||||
sleep "$delay_seconds"
|
||||
delay_seconds=$((delay_seconds * 2))
|
||||
done
|
||||
|
||||
- name: node_modules restored from cache
|
||||
if: steps.node-modules.outputs.cache-hit == 'true'
|
||||
shell: bash
|
||||
run: echo "node_modules restored from cache (key hit) — npm ci skipped"
|
||||
|
||||
16
.github/dependabot.yml
vendored
16
.github/dependabot.yml
vendored
@@ -58,6 +58,22 @@ updates:
|
||||
# on the VPS — so keep auto-bumps frozen (no update-types = ignore every version).
|
||||
# Migrate it intentionally, not via dependabot (#4050).
|
||||
- dependency-name: "@huggingface/transformers"
|
||||
# onnxruntime-node is the OTHER HALF of the @huggingface/transformers pair frozen
|
||||
# above: the hoisted copy must equal the exact version transformers pins, or npm
|
||||
# nests a second ABI-incompatible native copy (contract test
|
||||
# tests/unit/onnxruntime-single-copy.test.ts, pair established in #9962). A solo
|
||||
# bump can never be correct — it only ever moves together with transformers, in
|
||||
# the same deliberate migration PR. Freezing it keeps the production group PRs
|
||||
# (e.g. #12219) from being born red on the pair contract.
|
||||
- dependency-name: "onnxruntime-node"
|
||||
# eslint-plugin-react-hooks is pinned to 7.0.1 by a contract test
|
||||
# (tests/unit/eslint-react-hooks-version-pinned.test.ts) until the 7.1.1 rule set
|
||||
# is adopted deliberately — that adoption needs a full cold lint run and its own
|
||||
# PR (the #12146 react-hooks migration finished on 2026-09-01, so the path is
|
||||
# open; the bump still must not ride a dependabot group, where it reds the
|
||||
# development group PRs, e.g. #12220). Remove this ignore in the adoption PR
|
||||
# together with the pin test.
|
||||
- dependency-name: "eslint-plugin-react-hooks"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
|
||||
@@ -3477,7 +3477,7 @@ export function createOmniRouteProviderHook(
|
||||
|
||||
// ── Combo LCD across nested combo-refs (T-NN) ───────────────────────
|
||||
// Combos can nest other combos via `kind: "combo-ref"` members
|
||||
// (e.g. MASTER-LIGHT contains OldLLM, KIRO, Opecode Zen FREE). The
|
||||
// (e.g. MASTER-LIGHT contains LEGACY, KIRO, Opecode Zen FREE). The
|
||||
// nested combo's own `limit.context` is computed below in this same
|
||||
// loop, so we need a fixpoint iteration: if a combo-ref points at a
|
||||
// combo not yet processed, defer this combo and try again after the
|
||||
@@ -4495,7 +4495,7 @@ export function buildStaticProviderEntry(
|
||||
// ── Combo LCD across nested combo-refs (T-NN mirror) ─────────────────
|
||||
// Mirror of the dynamic-catalog fixpoint iteration: combos can nest
|
||||
// other combos via `kind: "combo-ref"` members (e.g. MASTER-LIGHT
|
||||
// contains OldLLM, KIRO, Opecode Zen FREE). The nested combo's own
|
||||
// contains LEGACY, KIRO, Opecode Zen FREE). The nested combo's own
|
||||
// capabilities and limits are computed in this same loop, so we need
|
||||
// a fixpoint pass: if a combo-ref points at a combo not yet processed,
|
||||
// defer this combo and try again after the sibling combos catch up.
|
||||
|
||||
@@ -641,13 +641,13 @@ test("models(): combos fetcher receives the resolved baseURL + apiKey", async ()
|
||||
|
||||
test("models(): nested combo-ref context is the min of nested + raw members", async () => {
|
||||
// Top-level combo MASTER-LIGHT has 1 raw model (claude-primary, 200k)
|
||||
// and 2 combo-refs: OldLLM (8k member) and KIRO (32k member). The OLD
|
||||
// and 2 combo-refs: LEGACY (8k member) and KIRO (32k member). The OLD
|
||||
// plugin would advertise 200k (only the raw model); the fix should
|
||||
// make it advertise 8k (the bottleneck across the member graph).
|
||||
const modelsFetcher = stubModelsFetcher([
|
||||
MODEL_PRIMARY,
|
||||
{
|
||||
id: "oldllm-member-1",
|
||||
id: "legacy-member-1",
|
||||
context_length: 8_000,
|
||||
max_output_tokens: 4_000,
|
||||
capabilities: {
|
||||
@@ -677,9 +677,9 @@ test("models(): nested combo-ref context is the min of nested + raw members", as
|
||||
]);
|
||||
const combosFetcher = stubCombosFetcher([
|
||||
{
|
||||
id: "oldllm",
|
||||
name: "OldLLM",
|
||||
models: [{ id: "s1", kind: "model", model: "oldllm-member-1", weight: 100 }],
|
||||
id: "legacy",
|
||||
name: "LEGACY",
|
||||
models: [{ id: "s1", kind: "model", model: "legacy-member-1", weight: 100 }],
|
||||
},
|
||||
{
|
||||
id: "kiro",
|
||||
@@ -691,7 +691,7 @@ test("models(): nested combo-ref context is the min of nested + raw members", as
|
||||
name: "MASTER-LIGHT",
|
||||
models: [
|
||||
{ id: "r1", kind: "model", model: "claude-primary", weight: 50 },
|
||||
{ id: "r2", kind: "combo-ref", comboName: "OldLLM", weight: 25 },
|
||||
{ id: "r2", kind: "combo-ref", comboName: "LEGACY", weight: 25 },
|
||||
{ id: "r3", kind: "combo-ref", comboName: "KIRO", weight: 25 },
|
||||
],
|
||||
},
|
||||
@@ -706,6 +706,6 @@ test("models(): nested combo-ref context is the min of nested + raw members", as
|
||||
assert.equal(
|
||||
masterLight.limit.context,
|
||||
8_000,
|
||||
`expected 8_000 (OldLLM bottleneck), got ${masterLight.limit.context}`
|
||||
`expected 8_000 (LEGACY bottleneck), got ${masterLight.limit.context}`
|
||||
);
|
||||
});
|
||||
|
||||
73
AGENTS.md
73
AGENTS.md
@@ -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, 354 LLM providers, auto-fallback.
|
||||
|
||||
| Layer | Location | Purpose |
|
||||
| ------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
@@ -58,7 +58,7 @@ Repository map and Reference Documentation sections below.
|
||||
| Services | `open-sse/services/` | Combo routing, rate limits, caching, etc |
|
||||
| Database | `src/lib/db/` | SQLite domain modules (167 migrations) |
|
||||
| Domain/Policy | `src/domain/` | Policy engine, cost rules, fallback logic |
|
||||
| MCP Server | `open-sse/mcp-server/` | 110 tools (44 canonical + memory/skill/GitHub/pool/gamification/plugin/Notion/Obsidian/local-corpus/RTK modules), 3 transports (stdio / SSE / Streamable HTTP), 33 scopes |
|
||||
| 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 |
|
||||
| Skills | `src/lib/skills/` | Extensible skill framework |
|
||||
| Memory | `src/lib/memory/` | Persistent conversational memory |
|
||||
@@ -83,7 +83,7 @@ Client → /v1/chat/completions (Next.js route)
|
||||
|
||||
API routes follow a consistent pattern: `Route → CORS preflight → Zod body validation → Optional auth (extractApiKey/isValidApiKey) → API key policy enforcement → Handler delegation (open-sse)`. No global Next.js middleware — interception is route-specific.
|
||||
|
||||
**Combo routing** (`open-sse/services/combo.ts`): 19 public strategies (priority, weighted, fill-first, round-robin, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, cache-optimized, context-relay, fusion, pipeline). Each target calls `handleSingleModel()` which wraps `handleChatCore()` with per-target error handling and circuit breaker checks. The `fusion` strategy is the exception: it fans out to a panel of models in parallel, then a judge model synthesizes one final answer (`open-sse/services/fusion.ts`). See `docs/routing/AUTO-COMBO.md` for the 15-factor Auto-Combo scoring + the full strategy table and `docs/architecture/RESILIENCE_GUIDE.md` for the 3 resilience layers.
|
||||
**Combo routing** (`open-sse/services/combo.ts`): 19 public strategies (priority, weighted, fill-first, round-robin, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, cache-optimized, context-relay, fusion, pipeline). Each target calls `handleSingleModel()` which wraps `handleChatCore()` with per-target error handling and circuit breaker checks. The `fusion` strategy is the exception: it fans out to a panel of models in parallel, then a judge model synthesizes one final answer (`open-sse/services/fusion.ts`). See `docs/routing/AUTO-COMBO.md` for the 16-factor Auto-Combo scoring + the full strategy table and `docs/architecture/RESILIENCE_GUIDE.md` for the 3 resilience layers.
|
||||
|
||||
---
|
||||
|
||||
@@ -110,26 +110,36 @@ upstream/service level, so one unhealthy provider does not slow down every reque
|
||||
- Shared wrappers: `open-sse/services/accountFallback.ts`
|
||||
- Persisted state table: `domain_circuit_breakers`
|
||||
|
||||
**States**:
|
||||
**States** (4 — `src/shared/utils/circuitBreaker.ts`):
|
||||
|
||||
- `CLOSED`: normal traffic is allowed.
|
||||
- `DEGRADED`: early-warning band — failures crossed the degradation threshold but not the
|
||||
breaker threshold yet; traffic still flows, dashboards show the warning.
|
||||
- `OPEN`: provider is temporarily blocked; callers get a provider-circuit-open response
|
||||
or combo routing skips to another target.
|
||||
- `HALF_OPEN`: reset timeout has elapsed; allow a probe request. Success closes the
|
||||
breaker, failure opens it again.
|
||||
|
||||
**Defaults** (`open-sse/config/constants.ts` → `PROVIDER_PROFILES`). Two thresholds live side by
|
||||
side — do not confuse them:
|
||||
**Defaults** (`open-sse/config/constants.ts` → `PROVIDER_PROFILES`, consumed via
|
||||
`DEFAULT_RESILIENCE_SETTINGS.providerBreaker` in `src/lib/resilience/settings.ts` →
|
||||
`getCircuitBreaker(provider, …)` in `src/sse/handlers/chatHelpers.ts`). The whole-provider
|
||||
breaker runs on `circuitBreakerThreshold` / `circuitBreakerReset`:
|
||||
|
||||
| Profile | `providerFailureThreshold` (whole provider) | `providerCooldownMs` | `circuitBreakerThreshold` (one connection) | `circuitBreakerReset` |
|
||||
| ------- | ------------------------------------------: | -------------------: | -----------------------------------------: | --------------------: |
|
||||
| OAuth | `10` | `5min` | `8` | `60s` |
|
||||
| API key | `15` | `10min` | `12` | `30s` |
|
||||
| Local | `2` | `1min` | `2` | `15s` |
|
||||
| Profile | degrades at | opens at (`circuitBreakerThreshold`) | reset (`circuitBreakerReset`) |
|
||||
| ------- | ----------: | -----------------------------------: | ----------------------------: |
|
||||
| OAuth | `5` | `8` | `60s` |
|
||||
| API key | `7` | `12` | `30s` |
|
||||
| Local | (derived) | `2` | `15s` |
|
||||
|
||||
The provider-level thresholds were scaled up for deployments with 500+ connections (OAuth was
|
||||
`3`, API key was `5`); every default is overridable through the `OMNIROUTE_PROVIDER_BREAKER_*`
|
||||
and `OMNIROUTE_CIRCUIT_BREAKER_*` env vars.
|
||||
`PROVIDER_PROFILES` also defines `providerFailureThreshold` (10/15/2),
|
||||
`providerFailureWindowMs` (15/30/5 min) and `providerCooldownMs` (5/10/1 min): these power the
|
||||
**window gate of the opt-in global Provider Cooldown** (`PROVIDER_COOLDOWN_ENABLED`, default
|
||||
off) — a provider-level entry in `open-sse/services/providerCooldownTracker.ts` only counts as
|
||||
cooling after `providerFailureThreshold` failures inside `providerFailureWindowMs`, and then
|
||||
cools for `providerCooldownMs`. They are NOT the live breaker's thresholds — do not tune them
|
||||
expecting breaker behavior. Every default is overridable through the
|
||||
`OMNIROUTE_PROVIDER_BREAKER_*` and `OMNIROUTE_CIRCUIT_BREAKER_*` env vars; the
|
||||
runtime-accurate reference table lives in `docs/architecture/RESILIENCE_GUIDE.md`.
|
||||
|
||||
Only provider-level failure statuses should trip the provider breaker:
|
||||
|
||||
@@ -242,7 +252,7 @@ Read the nearest `AGENTS.md` and the linked deep-dive before making a non-trivia
|
||||
| Streaming request handling | `open-sse/handlers/` | [`docs/architecture/ARCHITECTURE.md`](docs/architecture/ARCHITECTURE.md) |
|
||||
| Provider execution and translation | `open-sse/executors/`, `open-sse/translator/` | [`docs/architecture/CODEBASE_DOCUMENTATION.md`](docs/architecture/CODEBASE_DOCUMENTATION.md) |
|
||||
| Routing and resilience | `open-sse/services/` | [`open-sse/services/AGENTS.md`](open-sse/services/AGENTS.md), [`docs/routing/AUTO-COMBO.md`](docs/routing/AUTO-COMBO.md) |
|
||||
| Database and migrations | `src/lib/db/`, `db/migrations/` | [`src/lib/db/AGENTS.md`](src/lib/db/AGENTS.md) |
|
||||
| Database and migrations | `src/lib/db/`, `src/lib/db/migrations/` | [`src/lib/db/AGENTS.md`](src/lib/db/AGENTS.md) |
|
||||
| Domain policy | `src/domain/` | [`docs/architecture/ARCHITECTURE.md`](docs/architecture/ARCHITECTURE.md) |
|
||||
| MCP and A2A | `open-sse/mcp-server/`, `src/lib/a2a/` | [`docs/frameworks/MCP-SERVER.md`](docs/frameworks/MCP-SERVER.md), [`docs/frameworks/A2A-SERVER.md`](docs/frameworks/A2A-SERVER.md) |
|
||||
| Agent features | `src/lib/{acp,memory,skills,cloudAgent}/` | [`docs/frameworks/AGENT_PROTOCOLS_GUIDE.md`](docs/frameworks/AGENT_PROTOCOLS_GUIDE.md), [`docs/frameworks/SKILLS.md`](docs/frameworks/SKILLS.md) |
|
||||
@@ -254,13 +264,13 @@ Read the nearest `AGENTS.md` and the linked deep-dive before making a non-trivia
|
||||
## File placement & repo-root hygiene
|
||||
|
||||
- **Test files**: ALL unit tests, integration tests, ecosystem tests, or Vitest files MUST strictly be placed within the `tests/` directory (e.g., `tests/unit/`, `tests/integration/`). NEVER create test files in the project root (`/`).
|
||||
- **Scripts and utilities**: ALL maintenance, debugging, generation, or experimental scripts (`.cjs`, `.mjs`, `.js`, `.ts`) MUST be placed strictly inside one of the `scripts/` subfolders (`build/`, `dev/`, `check/`, `docs/`, `i18n/`, `ad-hoc/`, `quality/`, `release/`, `ci/`, `ops/`, `perf/`, `research/`, `sre/`, `vps/`, `homolog/`, `raycast/`, `skills/`, `test/`, `cli/`, `compression/`, `compression-eval/`, `devin-bridge/`, `docker/`, `features/`, `router-eval/`). One-shot or experimental code goes under `scripts/ad-hoc/`. NEVER dump loose scripts in the project root (`/`) or the top-level `scripts/` folder.
|
||||
- **Scripts and utilities**: ALL maintenance, debugging, generation, or experimental scripts (`.cjs`, `.mjs`, `.js`, `.ts`) MUST be placed strictly inside one of the `scripts/` subfolders (`build/`, `dev/`, `check/`, `docs/`, `i18n/`, `ad-hoc/`, `quality/`, `release/`, `ci/`, `ops/`, `perf/`, `research/`, `sre/`, `vps/`, `homolog/`, `packs/`, `skills/`, `test/`, `cli/`, `compression/`, `compression-eval/`, `devin-bridge/`, `docker/`, `features/`, `router-eval/`). One-shot or experimental code goes under `scripts/ad-hoc/`. NEVER dump loose scripts in the project root (`/`) or the top-level `scripts/` folder.
|
||||
|
||||
**The project root MUST ONLY contain:**
|
||||
|
||||
- Configuration files (`vitest.config.ts`, `next.config.mjs`, `eslint.config.mjs`, `tsconfig*.json`, `playwright.config.ts`, `prettier.config.mjs`, `postcss.config.mjs`, `sonar-project.properties`, `fly.toml`, `docker-compose*.yml`, `Dockerfile`)
|
||||
- Dependency files (`package.json`, `package-lock.json`)
|
||||
- Documentation files (`README.md`, `CHANGELOG.md`, `ROADMAP.md`, `LICENSE`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `CONTRIBUTING.md`, `SECURITY.md`, `CODE_OF_CONDUCT.md`, `llm.txt`, `Tuto_Qdrant.md`)
|
||||
- Documentation files (`README.md`, `CHANGELOG.md`, `ROADMAP.md`, `LICENSE`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `CONTRIBUTING.md`, `SECURITY.md`, `CODE_OF_CONDUCT.md`, `llm.txt`)
|
||||
- CI/CD files and ignore definitions (`.gitignore`, `.dockerignore`, `.npmignore`, `.npmrc`, `.node-version`, `.nvmrc`, `.env.example`)
|
||||
|
||||
When creating _any_ validation tests or one-off logic scripts, default to `scripts/ad-hoc/` or `tests/unit/` according to your goals. Do not pollute the `/` root context.
|
||||
@@ -333,6 +343,7 @@ Documentation must describe verified behavior, not plausible behavior.
|
||||
|
||||
### Adding a New Provider
|
||||
|
||||
0. Check `docs/reference/REMOVED_PROVIDERS.md` first — providers removed at their operator's request must never be reintroduced (guarded by `tests/unit/removed-providers-blocklist.test.ts`)
|
||||
1. Register in `src/shared/constants/providers.ts` (Zod-validated at load)
|
||||
2. Add executor in `open-sse/executors/` if custom logic needed (extend `BaseExecutor`)
|
||||
3. Add translator in `open-sse/translator/` if non-OpenAI format
|
||||
@@ -361,11 +372,11 @@ Documentation must describe verified behavior, not plausible behavior.
|
||||
1. Add tool definition in `open-sse/mcp-server/tools/` with Zod input schema + async handler
|
||||
2. Register in tool set (wired by `createMcpServer()`)
|
||||
3. Assign to appropriate scope(s)
|
||||
4. Write tests (tool invocation logged to `mcp_audit` table)
|
||||
4. Write tests (tool invocation logged to the `mcp_tool_audit` table)
|
||||
|
||||
### Adding a New A2A Skill
|
||||
|
||||
1. Create skill in `src/lib/a2a/skills/` (5 already exist: smart-routing, quota-management, provider-discovery, cost-analysis, health-report)
|
||||
1. Create skill in `src/lib/a2a/skills/` (6 already exist: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
2. Skill receives task context (messages, metadata) → returns structured result
|
||||
3. Register in `A2A_SKILL_HANDLERS` in `src/lib/a2a/taskExecution.ts`
|
||||
4. Expose in `src/app/.well-known/agent.json/route.ts` (Agent Card)
|
||||
@@ -374,7 +385,7 @@ Documentation must describe verified behavior, not plausible behavior.
|
||||
|
||||
### Adding a New Cloud Agent
|
||||
|
||||
1. Create agent class in `src/lib/cloudAgent/agents/` extending `CloudAgentBase` (3 already exist: codex-cloud, devin, jules)
|
||||
1. Create agent class in `src/lib/cloudAgent/agents/` extending `CloudAgentBase` (4 already exist: codex-cloud, devin, jules, cursor-cloud)
|
||||
2. Implement `createTask`, `getStatus`, `approvePlan`, `sendMessage`, `listSources`
|
||||
3. Register in `src/lib/cloudAgent/registry.ts`
|
||||
4. Add OAuth/credentials handling if needed (`src/lib/oauth/providers/`)
|
||||
@@ -385,7 +396,7 @@ Documentation must describe verified behavior, not plausible behavior.
|
||||
1. Create installer in `src/lib/services/installers/{name}.ts` modeled on `ninerouter.ts` (use `runNpm` from `installers/utils.ts` — no shell interpolation, hard rule #13).
|
||||
2. Register the service in `src/lib/services/bootstrap.ts` (add to `SERVICES[]` array and extend `buildSpawnArgsFactory()`).
|
||||
3. Add a DB seed row for the new service in `src/lib/db/migrations/` (`version_manager` table, `status='not_installed'`, `auto_start=0`).
|
||||
4. Create 7 API endpoints under `src/app/api/services/{name}/` (`_lib.ts`, `install`, `start`, `stop`, `restart`, `update`, `status`, `auto-start`). All delegate errors through `createErrorResponse()`. The shared `logs` endpoint is already wired via `[name]/logs/route.ts`.
|
||||
4. Create 8 API endpoints under `src/app/api/services/{name}/` (`_lib.ts`, `install`, `start`, `stop`, `restart`, `update`, `status`, `auto-start`, `auto-restart-adopted`). All delegate errors through `createErrorResponse()`. The shared `logs` endpoint is already wired via `[name]/logs/route.ts`.
|
||||
5. Verify `/api/services/` is in `LOCAL_ONLY_API_PREFIXES` in `src/server/authz/routeGuard.ts`; add a test asserting `isLocalOnlyPath()` returns `true` for the new prefix if you add one (hard rule #17).
|
||||
6. Add a UI tab in `src/app/(dashboard)/dashboard/providers/services/tabs/` reusing `ServiceStatusCard`, `ServiceLifecycleButtons`, `ServiceLogsPanel`.
|
||||
7. Document in `docs/frameworks/EMBEDDED-SERVICES.md` (update §1 service table + §4 API reference) and `docs/openapi.yaml`.
|
||||
@@ -412,7 +423,7 @@ For any non-trivial change, read the matching deep-dive first:
|
||||
| Repo navigation | `docs/architecture/REPOSITORY_MAP.md` |
|
||||
| Architecture | `docs/architecture/ARCHITECTURE.md` |
|
||||
| Engineering reference | `docs/architecture/CODEBASE_DOCUMENTATION.md` |
|
||||
| Auto-Combo (15-factor scoring, 19 strategies) | `docs/routing/AUTO-COMBO.md` |
|
||||
| Auto-Combo (16-factor scoring, 19 strategies) | `docs/routing/AUTO-COMBO.md` |
|
||||
| Resilience (3 mechanisms) | `docs/architecture/RESILIENCE_GUIDE.md` |
|
||||
| Reasoning replay | `docs/routing/REASONING_REPLAY.md` |
|
||||
| Skills framework | `docs/frameworks/SKILLS.md` |
|
||||
@@ -438,7 +449,7 @@ For any non-trivial change, read the matching deep-dive first:
|
||||
| VS Code Copilot Chat (OmniCopilot extension) | `docs/guides/VSCODE-COPILOT.md` |
|
||||
| Release flow | `docs/ops/RELEASE_CHECKLIST.md` |
|
||||
| Embedded services | `docs/frameworks/EMBEDDED-SERVICES.md` |
|
||||
| Quality gates (~80 scripts, allowlist policy) | `docs/architecture/QUALITY_GATES.md` |
|
||||
| Quality gates (~90 scripts, allowlist policy) | `docs/architecture/QUALITY_GATES.md` |
|
||||
|
||||
---
|
||||
|
||||
@@ -484,6 +495,12 @@ Why this matters: fixing bug A while opening bug B is worse than not fixing at a
|
||||
pipeline, and A2A skills.
|
||||
- Do not close a contributor pull request after using its code; merge it through GitHub so
|
||||
the contributor receives credit.
|
||||
- **Never merge a PR that touches an agent-instruction surface without explicit operator
|
||||
approval** — `CLAUDE.md`, `AGENTS.md`, `GEMINI.md`, `llm.txt` (+ mirrors) and
|
||||
`skills/**/SKILL.md` are executed as authority by every AI session; a merged instruction
|
||||
compromises every future agent run. Check with `gh pr diff <N> --name-only` before any
|
||||
merge. Incident record: PR #11770 (2026-09-01) told agents to execute a third-party
|
||||
setup script and was swept in by a merge campaign; reverted in #12249.
|
||||
|
||||
---
|
||||
|
||||
@@ -629,8 +646,8 @@ focused checks, and use a Conventional Commit message (for example, `docs: slim
|
||||
|
||||
## Environment
|
||||
|
||||
- **Runtime**: Node.js ≥22.0.0 <23 || ≥24.0.0 <27, ES Modules. This is the **only supported** runtime for the published `omniroute` CLI, the server, and the test suites (`node:test` + vitest) — `engines.node` is authoritative and end users never need Bun. A **best-effort `bun:sqlite` compatibility path** exists so a global Bun install (`bun install -g omniroute`) can start without `better-sqlite3` (driver adapter + Bun-aware process spawning); it is **not** a supported runtime — no support guarantees — and every Bun-specific runtime change MUST preserve the Node driver/fallback chain and ship a Bun test (`test:bun:db`) or an explicit reason why the path is Node-only.
|
||||
- **Bun (build/dev script runner + compatibility smoke only)**: Bun `1.3.14` is pinned as an **exact devDependency** (provisioned through the existing `npm ci` via the lockfile's `@oven/bun-*` platform binaries — no `setup-bun`/ad-hoc install). It is used **only** to execute a small, allow-listed set of TypeScript **gate/generator scripts** (replacing `node --import tsx` for startup speed): the CI checks `check:provider-consistency`, `check:compression-budget`, `check:known-symbols`, and the non-CI `gen:provider-reference`, `bench:compression` — plus the focused `test:bun:db` compatibility smoke suite for the best-effort `bun:sqlite` path. **Do NOT** widen Bun to `npm install`, the build (`build:cli*`), `check:pack-artifact`, the supported published runtime, or the main test runners — those stay on Node. Any new Bun-invoking gate/generator script must be validated byte-identical against its `node --import tsx` output first. After pulling the lockfile change, run `npm install` so `bun` resolves locally (a stale `node_modules` will fail those scripts with `bun: not found`).
|
||||
- **Runtime**: Node.js ≥22.22.2 <23 || ≥24.0.0 <27, ES Modules. This is the **only supported** runtime for the published `omniroute` CLI, the server, and the test suites (`node:test` + vitest) — `engines.node` is authoritative and end users never need Bun. A **best-effort `bun:sqlite` compatibility path** exists so a global Bun install (`bun install -g omniroute`) can start without `better-sqlite3` (driver adapter + Bun-aware process spawning); it is **not** a supported runtime — no support guarantees — and every Bun-specific runtime change MUST preserve the Node driver/fallback chain and ship a Bun test (`test:bun:db`) or an explicit reason why the path is Node-only.
|
||||
- **Bun (build/dev script runner + compatibility smoke only)**: Bun `1.4.0` is pinned as an **exact devDependency** (provisioned through the existing `npm ci` via the lockfile's `@oven/bun-*` platform binaries — no `setup-bun`/ad-hoc install). It is used **only** to execute a small, allow-listed set of TypeScript **gate/generator scripts** (replacing `node --import tsx` for startup speed): the CI checks `check:provider-consistency`, `check:compression-budget`, `check:known-symbols`, and the non-CI `gen:provider-reference`, `bench:compression` — plus the focused `test:bun:db` compatibility smoke suite for the best-effort `bun:sqlite` path. **Do NOT** widen Bun to `npm install`, the build (`build:cli*`), `check:pack-artifact`, the supported published runtime, or the main test runners — those stay on Node. Any new Bun-invoking gate/generator script must be validated byte-identical against its `node --import tsx` output first. After pulling the lockfile change, run `npm install` so `bun` resolves locally (a stale `node_modules` will fail those scripts with `bun: not found`).
|
||||
- **TypeScript**: 6.0+, target ES2022, module esnext, resolution bundler
|
||||
- **Path aliases**: `@/*` → `src/`, `@omniroute/open-sse` → `open-sse/`, `@omniroute/open-sse/*` → `open-sse/*`
|
||||
- **Default port**: 20128 (API + dashboard on same port)
|
||||
@@ -642,12 +659,12 @@ focused checks, and use a Conventional Commit message (for example, `docs: slim
|
||||
|
||||
## Quality Gates & Ratchets
|
||||
|
||||
OmniRoute has **~80 quality-gate scripts** (`scripts/check/` + `scripts/quality/`) wired
|
||||
OmniRoute has **~90 quality-gate scripts** (`scripts/check/` + `scripts/quality/`) wired
|
||||
across **9 gate-running jobs** in `.github/workflows/ci.yml` (`lint`, `quality-gate`,
|
||||
`quality-extended`, `docs-sync-strict`, `i18n-ui-coverage`, `i18n`, `pr-test-policy`,
|
||||
`test-vitest`, `sonarqube`), plus the `quality.yml` fast-gates job (PR→`release/**`) and
|
||||
3 nightly workflows (`nightly-property`, `nightly-resilience`, `nightly-llm-security`;
|
||||
`nightly-mutation` once merged). Full inventory, per-job breakdown, and operational
|
||||
5 quality nightly workflows (`nightly-property`, `nightly-resilience`,
|
||||
`nightly-llm-security`, `nightly-mutation`, `nightly-schemathesis`). Full inventory, per-job breakdown, and operational
|
||||
procedures are in [`docs/architecture/QUALITY_GATES.md`](docs/architecture/QUALITY_GATES.md).
|
||||
|
||||
**Quick reference:**
|
||||
|
||||
15
CHANGELOG.md
15
CHANGELOG.md
@@ -716,7 +716,6 @@ _By commits in `ed2db6cb19..v3.8.50`, author identities consolidated via `.mailm
|
||||
- **[TS7] fix(types): normalize DuckDuckGo request messages** ([#9847](https://github.com/diegosouzapw/OmniRoute/pull/9847), original [#9797](https://github.com/diegosouzapw/OmniRoute/pull/9797)) — thanks @backryun
|
||||
- **[TS7] fix(types): expose SQLite transaction state** ([#9848](https://github.com/diegosouzapw/OmniRoute/pull/9848), original [#9796](https://github.com/diegosouzapw/OmniRoute/pull/9796)) — thanks @backryun
|
||||
- **[TS7] fix(types): validate default executor pool config** ([#9849](https://github.com/diegosouzapw/OmniRoute/pull/9849), original [#9795](https://github.com/diegosouzapw/OmniRoute/pull/9795)) — thanks @backryun
|
||||
- **[TS7] fix(types): preserve The Old LLM proxy contracts** ([#9850](https://github.com/diegosouzapw/OmniRoute/pull/9850), original [#9793](https://github.com/diegosouzapw/OmniRoute/pull/9793)) — thanks @backryun
|
||||
- **[TS7] fix(types): normalize Gemini Business credentials** ([#9851](https://github.com/diegosouzapw/OmniRoute/pull/9851), original [#9792](https://github.com/diegosouzapw/OmniRoute/pull/9792)) — thanks @backryun
|
||||
- **[TS7] fix(types): preserve Claude thinking body contracts** ([#9852](https://github.com/diegosouzapw/OmniRoute/pull/9852), original [#9791](https://github.com/diegosouzapw/OmniRoute/pull/9791)) — thanks @backryun
|
||||
- **fix(response): strip internal reasoning placeholder from all reasoning fields** ([#9853](https://github.com/diegosouzapw/OmniRoute/pull/9853), original [#9790](https://github.com/diegosouzapw/OmniRoute/pull/9790)) — thanks @adevwithpurpose
|
||||
@@ -888,7 +887,7 @@ _By commits in `ed2db6cb19..v3.8.50`, author identities consolidated via `.mailm
|
||||
- **fix(combo):** defer the known-context-overflow hard rejection for compressible requests so compression runs before the final context gate, instead of a raw-body estimate 400'ing generic Responses clients targeting a large model before OmniRoute can shrink it ([#10225](https://github.com/diegosouzapw/OmniRoute/issues/10225))
|
||||
- **fix(api):** deleting a manually-added custom model no longer tombstones a provider-synced model that shares its id. `DELETE /api/provider-models` is addressed by `provider` + `model` alone, so when both a custom row and a synced row existed for one id it removed both and wrote `isDeleted:true`. `replaceSyncedAvailableModelsForConnection` then filtered that id out of every subsequent re-import, so the provider could never resync — model sync kept reporting `added: N` while the catalog stayed empty and `/v1/models` never listed the model again, even though routing to it still worked. The custom row is now removed first and its presence is treated as the operator's intent, leaving the synced sibling importable; a synced-only delete still tombstones as before (#3199, #3782 unaffected) ([#10228](https://github.com/diegosouzapw/OmniRoute/pull/10228)) — thanks @Neuron-Mr-White
|
||||
- **Audio Bridge:** fix production transcription self-loop uploads so real audio reaches the configured STT provider instead of falling back to an unavailable-provider stub ([#10229](https://github.com/diegosouzapw/OmniRoute/pull/10229)).
|
||||
- **fix(api):** DeepSeek V4's native `max` reasoning tier is now reachable. DeepSeek accepts `reasoning_effort` `low`/`high`/`max` and maps `medium`/`xhigh` down to `high`, while OmniRoute's canonical vocabulary collapses `max` onto `xhigh` — so `{"effort":"max"}` silently resolved to `high` and the catalog never advertised a `max` tier (or its `<model>-max` variant). Following the existing `extendCodexGpt56EffortValues` precedent, the native tier is now preserved for `deepseek`/`ds` V4 models only; the global effort vocabulary is unchanged, routed namespaces (`openrouter/deepseek/…`, `tllm/deepseek_v4`, `oc/deepseek-v4-flash-free`) keep the canonical behavior, and an explicit client `reasoning_effort` still wins ([#10230](https://github.com/diegosouzapw/OmniRoute/pull/10230)) — thanks @Neuron-Mr-White
|
||||
- **fix(api):** DeepSeek V4's native `max` reasoning tier is now reachable. DeepSeek accepts `reasoning_effort` `low`/`high`/`max` and maps `medium`/`xhigh` down to `high`, while OmniRoute's canonical vocabulary collapses `max` onto `xhigh` — so `{"effort":"max"}` silently resolved to `high` and the catalog never advertised a `max` tier (or its `<model>-max` variant). Following the existing `extendCodexGpt56EffortValues` precedent, the native tier is now preserved for `deepseek`/`ds` V4 models only; the global effort vocabulary is unchanged, routed namespaces (`openrouter/deepseek/…`, `oc/deepseek-v4-flash-free`) keep the canonical behavior, and an explicit client `reasoning_effort` still wins ([#10230](https://github.com/diegosouzapw/OmniRoute/pull/10230)) — thanks @Neuron-Mr-White
|
||||
- **fix(providers):** FreeAIAPIKey now targets `api.freeaiapikey.com`, the host upstream names in its `410 endpoint_moved` response — every request through the provider was failing — and its catalog is resynced to the 10 models the live `/v1/models` actually serves ([#10233](https://github.com/diegosouzapw/OmniRoute/pull/10233))
|
||||
- **fix(providers):** MonsterAPI's deprecation now actually applies — the flag was written as `isDeprecated`, a key no consumer or schema reads, so the provider kept rendering as healthy in the dashboard, the onboarding wizard and the generated provider reference ([#10234](https://github.com/diegosouzapw/OmniRoute/pull/10234))
|
||||
- **fix(cliproxy):** read platform/arch at runtime via `os.platform()`/`os.arch()` in `binaryManager` so the embedded installer selects the Windows/ARM assets even when the release bundle is built on a Linux runner (fixes #10244)
|
||||
@@ -3000,7 +2999,6 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62
|
||||
- Stream model health probes for slow providers ([#7377](https://github.com/diegosouzapw/OmniRoute/pull/7377)) — thanks @JxnLexn
|
||||
- Refresh NVIDIA free metadata and detect catalog drift ([#7378](https://github.com/diegosouzapw/OmniRoute/pull/7378)) — thanks @JxnLexn
|
||||
- Reject invalid output token budgets ([#7379](https://github.com/diegosouzapw/OmniRoute/pull/7379)) — thanks @JxnLexn
|
||||
- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn
|
||||
- Restore proxy navigation and sidebar accordion state ([#7381](https://github.com/diegosouzapw/OmniRoute/pull/7381)) — thanks @JxnLexn
|
||||
- Expose proxy controls for no-auth providers ([#7419](https://github.com/diegosouzapw/OmniRoute/pull/7419)) — thanks @JxnLexn
|
||||
- Add reasoning-based model and effort routing ([#7607](https://github.com/diegosouzapw/OmniRoute/pull/7607)) — thanks @JxnLexn
|
||||
@@ -3442,7 +3440,7 @@ _Living section — bullets land here as PRs merge into `release/v3.8.47` (paral
|
||||
- **fix(cli):** `omniroute serve` no longer hangs silently on a readiness timeout ([#6321](https://github.com/diegosouzapw/OmniRoute/issues/6321)) — the child server's stdout was piped to `"ignore"` whenever `--log`/`OMNIROUTE_SHOW_LOG` wasn't set (the default), discarding any debug output, and `runWithSupervisor`'s `waitForServer(...).then((up) => { if (up) {...} })` had no `else` branch, so a boot that never became ready produced zero further output after "⏳ Starting server...". Stdout is now buffered alongside stderr (`ServerSupervisor.getRecentLog()`), and a timeout prints a clear diagnostic plus the buffered output instead of staying silent. Does not by itself explain why boot never completes on a given machine — see the issue for further reproduction. Regression guard: `tests/unit/cli-serve-readiness-timeout-6321.test.ts`.
|
||||
- **fix(pricing):** Pricing Sync dashboard no longer stuck on "Next Sync: Never" / "Synced Models: 0" ([#6325](https://github.com/diegosouzapw/OmniRoute/issues/6325)) — `pricingSync.ts` kept sync state (`lastSyncTime`, `lastSyncModelCount`) in module-level vars, but the background periodic sync (`instrumentation-node.ts`) and the dashboard status route (`/api/pricing/sync`) each import the module from separate Next.js standalone webpack chunks, giving each its own independent state; `getSyncStatus()` read the (empty) API-route instance's vars. Sync status is now additionally persisted to a new `pricing_sync_status` `key_value` namespace and `getSyncStatus()` falls back to it when the local module instance never ran a sync itself. Regression guard: `tests/unit/pricing-sync-cross-instance.test.ts`.
|
||||
- **fix(api):** stop spuriously 403-ing "Invalid request origin" on `POST /api/providers/health-autopilot/actions` for Docker/LAN dashboard requests ([#6277](https://github.com/diegosouzapw/OmniRoute/issues/6277)) — the route carried a duplicate per-route `validateBrowserMutationOrigin` check re-added by the v3.8.42 release squash after PR #5278 centralized origin enforcement in the authz pipeline; the pipeline strips `PEER_IP_HEADER` before forwarding, so the stale duplicate check could no longer resolve the LAN "direct-local-host" candidate and rejected legitimate same-origin LAN mutations (e.g. clicking "remove cooldown" when accessed via a LAN IP). Removed the duplicate check — origin validation is now solely enforced by the centralized pipeline check, which already handles this case correctly. Regression guard: `tests/unit/serial/provider-health-autopilot.test.ts`.
|
||||
- **fix(resilience):** a bare, unrecognized `403` from a no-credential (`authType:"none"`) provider like mimocode or theoldllm no longer permanently bans the connection ([#6315](https://github.com/diegosouzapw/OmniRoute/issues/6315), [#6345](https://github.com/diegosouzapw/OmniRoute/issues/6345)) — `classifyProviderError()`'s 403 branch only exempted `apikey` providers from the terminal `FORBIDDEN` classification, so these free/stateless proxies (no real account/credential to revoke) fell through to `FORBIDDEN` on the first unmatched 403 and got `isActive:false, testStatus:"banned"` with no cooldown or retry. The exemption now also covers `authType:"none"` providers, returning `null` (recoverable) so the existing connection-cooldown/retry layer handles it. Regression guard: `tests/unit/errorClassifier-noauth-403-6315.test.ts`.
|
||||
- **fix(resilience):** a bare, unrecognized `403` from a no-credential (`authType:"none"`) provider like mimocode no longer permanently bans the connection ([#6315](https://github.com/diegosouzapw/OmniRoute/issues/6315), [#6345](https://github.com/diegosouzapw/OmniRoute/issues/6345)) — `classifyProviderError()`'s 403 branch only exempted `apikey` providers from the terminal `FORBIDDEN` classification, so these free/stateless proxies (no real account/credential to revoke) fell through to `FORBIDDEN` on the first unmatched 403 and got `isActive:false, testStatus:"banned"` with no cooldown or retry. The exemption now also covers `authType:"none"` providers, returning `null` (recoverable) so the existing connection-cooldown/retry layer handles it. Regression guard: `tests/unit/errorClassifier-noauth-403-6315.test.ts`.
|
||||
- **fix(providers):** the **Auggie (Augment CLI)** executor no longer fails on Windows with `spawn EINVAL` ([#6304](https://github.com/diegosouzapw/OmniRoute/issues/6304)) — the global-npm install exposes `auggie` as a `.cmd` shim, which Node's `child_process.spawn` cannot launch on win32 without `shell: true`. Both spawn sites (streaming + the `auggie --version` test) now go through a shared `buildAuggieSpawnOptions()` that sets `shell: process.platform === "win32"`; the argv (built by `buildAuggieArgs()` with a registry-validated `model` and a trailing `--` end-of-options marker) is unchanged, so the argument-injection surface stays closed on non-Windows. Regression guard: `tests/unit/auggie-win32-spawn-6304.test.ts`.
|
||||
- **fix(api):** the dashboard **"Test model"** action is now a clean connection test ([#6240](https://github.com/diegosouzapw/OmniRoute/issues/6240)) — `modelTestRunner` sent its probe request without an explicit compression override, so whenever the operator's global `compression.enabled` flag was on the test call inherited compression (and any Output-Styles system prompt), polluting the result. The internal test requests now send `X-OmniRoute-Compression: off`, and `chatCore` honors an explicit `off` header even when `compression.enabled` is globally true. Regression guards: `tests/unit/model-test-runner-compression-off-6240.test.ts`, `tests/integration/test-model-compression-off-6240.test.ts`.
|
||||
- **fix(startup):** an update/restart could crash the whole server at boot with `TypeError: Cannot create property 'message' on string 'Database closed'`, masking the real failure and 500-ing every request until manually restarted ([#6560](https://github.com/diegosouzapw/OmniRoute/issues/6560), plausibly the root cause of #6594's post-upgrade 500) — `driverFactory.ts::preInitSqlJs()` cached its sql.js WASM adapter per file path in a `globalThis`-backed map for idempotency, but never checked whether the cached adapter had since been closed (e.g. by `gracefulShutdown`/`resetDbInstance` racing a reload); reusing that dead handle made the very next query throw sql.js's own bare string `"Database closed"` (not an `Error`) straight out of `instrumentation-node.ts`'s previously-unguarded `ensureDbInitialized()` call, and Next.js's internal `registerInstrumentation()` wrapper unconditionally does `err.message = ...` on whatever `register()` rejects with — assigning `.message` on a primitive string throws in strict mode, so the secondary `TypeError` is what actually crashed the process. Fixed in two parts: `preInitSqlJs()` now evicts a closed cached adapter and creates a fresh one instead of returning it; a new `ensureDbReadyForBoot()` wraps the DB-init call, normalizes any non-Error throw via `normalizeBootError()`, and retries once specifically for a transient "database closed" message (now succeeding against the fresh adapter) before re-throwing anything else as a real `Error`. Regression guard: `tests/unit/instrumentation-database-closed-6560.test.ts`.
|
||||
@@ -3998,7 +3996,6 @@ Thanks to everyone whose work landed in v3.8.45:
|
||||
- **feat(api):** expose a read-only provider plugin manifest at `GET /api/v1/provider-plugin-manifest` for sidecar/relay discovery. ([#6001](https://github.com/diegosouzapw/OmniRoute/pull/6001)) (thanks @KooshaPari)
|
||||
- **feat(sidecar):** advertise the provider manifest URL to Bifrost/CLIProxyAPI via the `X-OmniRoute-Provider-Manifest-Url` header (`OMNIROUTE_PROVIDER_MANIFEST_URL`). ([#6007](https://github.com/diegosouzapw/OmniRoute/pull/6007)) (thanks @KooshaPari)
|
||||
- **feat(autoCombo):** add a latency/speed-optimized routing mode (shared `rankBySpeed` scoring core) plus the `omniroute_pick_fastest_model` MCP tool. ([#6011](https://github.com/diegosouzapw/OmniRoute/pull/6011)) (thanks @KooshaPari)
|
||||
- **feat(providers):** refresh The Old LLM (Free) model catalog ([#5181](https://github.com/diegosouzapw/OmniRoute/issues/5181)) — seed the current free `/api/chatgpt` tier (GPT-5/5.1/5.2/5.3/5.4, o3/o4-mini, Gemini 3 Pro / 2.5 Pro / 2.0 Flash / 1.5 Flash, Claude 4.6 Opus/Sonnet & 4.5 Haiku, GPT-4o, Grok 4, DeepSeek V3/R1, Sonar Pro) while keeping the legacy alias IDs for saved-preference compatibility. Also fixes a latent routing bug: `mapModel()` now passes known upstream IDs through unchanged, so Gemini/o-series/Grok/DeepSeek/Sonar models no longer silently collapse onto `GPT_5_4`. Regression guard: `tests/unit/theoldllm-model-refresh-5181.test.ts`. (thanks @WslzGmzs)
|
||||
- **feat(resilience):** surface Codex **banked reset credits** per connected account ([#5199](https://github.com/diegosouzapw/OmniRoute/issues/5199)) — the Codex quota parsers (`buildCodexUsageQuotas`, `parseCodexUsageResponse`) now additively read `rate_limit_reset_credits.available_count` (+ optional `rate_limit_reached_type`) from the `/wham/usage` payload OmniRoute already fetches, and the provider-limits dashboard renders a **"Banked Reset Credits"** row when a positive count is present. Display-only and **fail-open** — the field is eligibility-gated, so accounts without it are unaffected (parsers never throw on absent/garbage shapes); redemption (an unofficial mutating endpoint) is intentionally out of scope. Regression guard: `tests/unit/codex-banked-reset-credits-5199.test.ts` (8). (thanks @ofekbetzalel)
|
||||
- **feat(providers):** add sign-up geo-restriction notices for **SenseNova** and **StepFun** ([#5462](https://github.com/diegosouzapw/OmniRoute/issues/5462)) — the provider add-form now warns that SenseNova's console appears to require a Chinese (+86) phone number with no documented international path, and that StepFun's default endpoint is its China platform while a global StepFun Open Platform (`platform.stepfun.ai`, operated by Sparkling AI Pte. Ltd., Singapore) with email/Google/Discord login exists for international users. Informational `notice` only — neither provider is disabled. Regression guard: `tests/unit/regional-provider-cn-notices-5462.test.ts`. (thanks @chirag127)
|
||||
- **feat(usage):** add on-demand period-scoped usage-data reset (Settings → System Storage) with a purge API and time-window selector. ([#5831](https://github.com/diegosouzapw/OmniRoute/pull/5831))
|
||||
@@ -5644,7 +5641,6 @@ Thanks to everyone whose work landed in v3.8.43:
|
||||
- **fix(sse): map `reasoning_effort` to DeepSeek V4's native `{high, max}` vocabulary** — DeepSeek V4 only understands `high`/`max` reasoning levels, so other `reasoning_effort` values are mapped onto its native vocabulary instead of being rejected. ([#4219](https://github.com/diegosouzapw/OmniRoute/pull/4219))
|
||||
- **fix(glm): default `max_tokens` and an extended timeout for GLM-5.2+ thinking** — GLM-5.2+ thinking responses are slow and need headroom, so OmniRoute now sets a sensible default `max_tokens` and a longer timeout for them. ([#4255](https://github.com/diegosouzapw/OmniRoute/pull/4255) — thanks @dhaern)
|
||||
- **fix(antigravity): default `includeThoughts` for modern Gemini models** — modern Gemini models on the Antigravity path now default to including thoughts so reasoning isn't silently dropped. ([#4180](https://github.com/diegosouzapw/OmniRoute/pull/4180) — thanks @dhaern)
|
||||
- **fix(provider-registry): add correct `contextLength` to theoldllm models** — fills in accurate context-window sizes for theoldllm's models. ([#4184](https://github.com/diegosouzapw/OmniRoute/pull/4184) — thanks @herjarsa)
|
||||
- **fix(models): expose combo model token limits** — `/v1/models` now reports token limits for combo models. ([#4189](https://github.com/diegosouzapw/OmniRoute/pull/4189) — thanks @megamen32)
|
||||
- **fix(combo): keep the passthrough quota fallback scoped** — prevents the passthrough quota fallback from leaking across unrelated targets. ([#4194](https://github.com/diegosouzapw/OmniRoute/pull/4194) — thanks @Svetznaniy33)
|
||||
- **fix(combo): opt proactive-fallback compression into the TV1 bail-out (no silent target drop)** — proactive-fallback compression now participates in the TV1 bail-out so a target is never silently dropped. ([#4228](https://github.com/diegosouzapw/OmniRoute/pull/4228))
|
||||
@@ -6304,7 +6300,6 @@ Thanks to everyone whose work landed in v3.8.43:
|
||||
- **fix(catalog):** Codex CLI model-catalog refresh no longer errors — `GET /v1/models` now returns a top-level `models: []` array for Codex clients (detected via the `originator` / `user-agent` = `codex_*` headers it sends on `GET /v1/models?client_version=...`), so `codex_models_manager` stops failing to decode the OpenAI-standard response and no longer logs `failed to refresh available models` on every startup. The array is intentionally empty: Codex replaces its built-in per-model agent prompt (`base_instructions`, ~21k chars) with whatever a populated entry carries for the selected model, so emitting our catalog would break Codex's agent behaviour — an empty list keeps Codex on its built-in model info (same inference as before, minus the error). Non-Codex OpenAI clients receive the unchanged `{object,data}` response. ([#3481](https://github.com/diegosouzapw/OmniRoute/pull/3481) — thanks @diegosouzapw)
|
||||
- **fix(provider):** Cursor's Responses-API-shaped bodies on `/chat/completions` are detected and handled — a body with `input` but no `messages` is now classified as `openai-responses` (instead of forcing `openai` and building from undefined `messages` → upstream 400); standard OpenAI clients are unaffected by the `messages===undefined` guard. ([#3490](https://github.com/diegosouzapw/OmniRoute/pull/3490) — thanks @borodulin)
|
||||
- **fix(sse):** numeric provider IDs normalized to strings across 4 more surfaces — extends #3427 to the Responses-API SSE passthrough (`response_id`/`item_id`/`call_id`), the buffered/flush path in `stream.ts`, the dedup-key builders, and `sseParser.ts`, preventing `undefined` lookups when IDs arrive as numbers. ([#3451](https://github.com/diegosouzapw/OmniRoute/pull/3451) — thanks @disafronov)
|
||||
- **fix(theoldllm):** `X-Request-Token` generated server-side, dropping the Playwright dependency — replicates the site's client `rie()` token (djb2 hash + `oldllm-client-2026` seed + UA prefix + 8-hex `crypto.randomUUID` suffix) directly, so The Old LLM no longer needs a headless browser to mint tokens. ([#3491](https://github.com/diegosouzapw/OmniRoute/pull/3491) — thanks @borodulin / @diegosouzapw)
|
||||
- **fix(combo):** parallel pre-screen + circuit-breaker fast-exit for priority combos — provider profiles and model availability for all targets are pre-screened concurrently (max 5), and targets whose circuit breaker is OPEN are skipped immediately, reducing first-token latency on multi-target priority combos. ([#3169](https://github.com/diegosouzapw/OmniRoute/pull/3169) — thanks @pizzav-xyz)
|
||||
- **fix(authz):** URL-tokenized client endpoints (`/api/v1/vscode/<key>/...`) authenticate again when the caller sends its own non-OmniRoute `Authorization` header — a non-`Bearer <token>` header (e.g. VS Code Copilot's own, or an empty `Bearer `) no longer short-circuits auth; it falls through to the path-scoped URL token (still validated downstream), instead of 401'ing under `REQUIRE_API_KEY=true`. ([#3504](https://github.com/diegosouzapw/OmniRoute/pull/3504) — thanks @zhiru / @diegosouzapw)
|
||||
- **fix(playground):** the dashboard provider Test playground works under `REQUIRE_API_KEY=true` — it previously sent the **masked** key (`sk-xxxx****yyyy`) as a bearer (always invalid → 401). It now authenticates via the dashboard session and sends only the key **id** (`x-omniroute-playground-key-id`); the gateway resolves the secret server-side, honored **only** for an authenticated session and never putting the key secret on the wire. ([#3503](https://github.com/diegosouzapw/OmniRoute/pull/3503) — thanks @zhiru / @diegosouzapw)
|
||||
@@ -6337,7 +6332,7 @@ Thanks to everyone whose work landed in v3.8.43:
|
||||
|
||||
- **fix(translator):** Vertex AI tool calls no longer fail with `400 Unknown name "id"` — the OpenAI-style `id` field is stripped from `functionCall`/`functionResponse` parts for `vertex`/`vertex-partner`; the public Gemini API still receives `id` as required for Gemini 3+ signature matching. ([#3457](https://github.com/diegosouzapw/OmniRoute/pull/3457) — thanks @nullbytef0x / @diegosouzapw)
|
||||
- **fix(claude):** Claude Code `claude-opus-4-8` tool calls no longer break with `tool call could not be parsed` — OmniRoute no longer force-injects `interleaved-thinking` / `advanced-tool-use` / `effort` beta flags the client never negotiated; clients sending their own `anthropic-beta` header control those betas themselves. ([#3458](https://github.com/diegosouzapw/OmniRoute/pull/3458) — thanks @Forcerecon / @diegosouzapw)
|
||||
- **fix(catalog):** imported/custom models on no-auth providers (e.g. The Old LLM) now appear in `GET /api/v1/models` and the Playground model selector — the eligibility gate required a DB connection row which no-auth providers never have, silently dropping every imported model for them. ([#3463](https://github.com/diegosouzapw/OmniRoute/pull/3463) — thanks @tjengbudi / @diegosouzapw)
|
||||
- **fix(catalog):** imported/custom models on no-auth providers now appear in `GET /api/v1/models` and the Playground model selector — the eligibility gate required a DB connection row which no-auth providers never have, silently dropping every imported model for them. ([#3463](https://github.com/diegosouzapw/OmniRoute/pull/3463) — thanks @tjengbudi / @diegosouzapw)
|
||||
- **fix(browser):** optional `cloakbrowser` import no longer causes bundle errors when the package is absent — the import is now wrapped in a dynamic require so the build succeeds on environments that don't install the optional dep. ([#3460](https://github.com/diegosouzapw/OmniRoute/pull/3460) — thanks @rdself)
|
||||
- **fix(claude-web):** claude-web session handling cleanup — corrects an edge case where session cookies were not properly refreshed after a Turnstile challenge, and removes stale wrapper code left over from the provider split. ([#3449](https://github.com/diegosouzapw/OmniRoute/pull/3449) — thanks @androw)
|
||||
- **fix(analytics):** SQL named params are now scoped per query context — a shared params object was being mutated across concurrent analytics queries, causing `SQLITE_MISUSE: named parameter not found` errors under load. ([#3447](https://github.com/diegosouzapw/OmniRoute/pull/3447) — thanks @ReqX)
|
||||
@@ -6513,8 +6508,7 @@ Thanks to everyone whose work landed in v3.8.14:
|
||||
|
||||
- **fix(dashboard):** Agent Bridge page (`/dashboard/tools/agent-bridge`) no longer crashes with "Internal Server Error" — the page replaced its well-shaped state with the raw `/api/tools/agent-bridge/state` response (`{ server, agents }`), leaving `serverState` undefined and throwing `Cannot read properties of undefined (reading 'running')`. A shared `normalizeAgentBridgeState()` now maps the route shape into the page contract (incl. `server.certExists → certTrusted`) and always returns safe defaults, used by both the SSR loader and the polling hook. (#3318 — thanks @tycronk20)
|
||||
- **fix(codex):** strip client-only params (`prompt_cache_retention`, `safety_identifier`, `user`) on the native `codex/` `/v1/responses` passthrough — Codex upstream rejects them with `400 Unsupported parameter`, which broke Factory Droid and any client injecting those fields. The chat-completions path already stripped them; the responses→responses passthrough now does too. (#3317 — thanks @tycronk20)
|
||||
- **fix(theoldllm):** stop the `[502]: Body is unusable: Body has already been read` error on the cached-token path — the executor read the same upstream `Response` body with `.text()` twice; it now reads it once and only re-reads after a token-rejection refetch. (#3296 — thanks @onizukashonan14-png)
|
||||
- **fix(dashboard):** keep no-auth providers (opencode, duckduckgo-web, theoldllm, veoaifree-web) visible under the "Show configured only" filter — they never create a connection row (`stats.total === 0`) but are always usable and already appear in `/v1/models`, so the filter now treats `displayAuthType === "no-auth"` as configured. (#3290 — thanks @uniQta)
|
||||
- **fix(dashboard):** keep no-auth providers (opencode, duckduckgo-web, veoaifree-web) visible under the "Show configured only" filter — they never create a connection row (`stats.total === 0`) but are always usable and already appear in `/v1/models`, so the filter now treats `displayAuthType === "no-auth"` as configured. (#3290 — thanks @uniQta)
|
||||
- **fix(dashboard):** refresh the connection list after a Codex/Claude/Gemini auth import — the import modals called `fetchData()` (which only reloads provider metadata), so a freshly-imported connection stayed invisible until a manual reload; they now call `fetchConnections()`. ([#3320](https://github.com/diegosouzapw/OmniRoute/pull/3320) — thanks @zhiru)
|
||||
- **fix(cli):** `omniroute update` no longer always fails on a global install — `getCurrentVersion()` and `createBackup()` now resolve `package.json`/`bin` relative to the script (`import.meta.url`) instead of `process.cwd()` (the user's working dir on a global npm/brew install → _"Could not determine current version"_), and the backup copies the `cli` directory with `cpSync({recursive:true})` instead of `copyFileSync`, which threw a swallowed `EISDIR` → _"Failed to create backup. Aborting"_. (#3295 — thanks @uniQta)
|
||||
- **fix(sse):** harden the passthrough stream against empty upstream responses — emit a synthetic retry chunk on an empty `choices: []` (fixes a Copilot Chat crash) and log empty post-`tool_calls` completions; also registers **MiniMax M3** (1M context) across 8 provider tiers. ([#3297](https://github.com/diegosouzapw/OmniRoute/pull/3297), #3110 — thanks @wilsonicdev)
|
||||
@@ -6606,7 +6600,6 @@ Thanks to everyone whose work landed in v3.8.12:
|
||||
|
||||
### ✨ New Features
|
||||
|
||||
- **theoldllm:** add The Old LLM — a free, Playwright-backed provider with dual-mode operation (cached browser token + direct fetch) bridged through a Vercel relay (#3217 — thanks @oyi77)
|
||||
- **codex:** add Codex login via OpenAI's browser-driven device authorization flow, exposed as a shareable "Adicionar Externo" public link (`/connect/codex/{token}`) so a third party can complete the OpenAI device login without dashboard access (#3195 — thanks @zhiru)
|
||||
- **proxy:** per-connection proxy distribution — `proxy_enabled` DB schema + Zod-validated resolution backend, automatic proxy-fallback selection when provider validation hits a network error, and a dashboard UI with per-connection toggles and a tag-filtered "Distribute Proxies" button (#3170, #3171, #3172 — thanks @pizzav-xyz)
|
||||
- **api:** `/v1/images/generations` and `/v1/images/edits` now resolve a bare combo/alias model name (e.g. `image`) to its single image target, and `/v1/images/edits` forwards multipart edits to custom OpenAI-compatible providers' `{base_url}/images/edits` (also accepting JSON/data-URL edit input) instead of rejecting everything but chatgpt-web (#3214, #3215 — thanks @ngocquynh85)
|
||||
|
||||
@@ -73,6 +73,9 @@ npm run dev
|
||||
npm run build # next build → .build/next/ then assembleStandalone → dist/
|
||||
npm run start
|
||||
|
||||
# Fast backend/API-only compile for contributor changes
|
||||
npm run build:contributor
|
||||
|
||||
# Release build (clean rebuild + HEAD sentinel — required for deploy)
|
||||
npm run build:release # rm -rf .build dist && build + writes dist/BUILD_SHA
|
||||
|
||||
@@ -80,6 +83,10 @@ npm run build:release # rm -rf .build dist && build + writes dist/BUILD_SHA
|
||||
PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
|
||||
```
|
||||
|
||||
The contributor build performs compile-only validation: it does not assemble the standalone
|
||||
distribution or build optional native packaging assets. Use the regular production build when
|
||||
you need to validate the shippable bundle.
|
||||
|
||||
### Build Output Layout
|
||||
|
||||
| Directory | Contents | Tracked |
|
||||
@@ -100,6 +107,11 @@ npm run build
|
||||
`npm run build:release` additionally cleans both directories first and writes
|
||||
`dist/BUILD_SHA` (= `git rev-parse --short HEAD`) as a deploy integrity sentinel.
|
||||
|
||||
`npm run build:contributor` uses the backend-only build profile. It temporarily stubs
|
||||
dashboard UI files while building, keeps API route handlers, and restores the original files
|
||||
after the build. Use `npm run build` for changes that affect the dashboard UI or for full
|
||||
release validation; the contributor profile is not a replacement for the release build.
|
||||
|
||||
> **VPS deploy note:** the remote image directory `/usr/lib/node_modules/omniroute/app/`
|
||||
> is unchanged. The deploy skills rsync the contents of `dist/` into it.
|
||||
> Only the in-repo build output path moved (`app/` → `dist/`).
|
||||
@@ -165,6 +177,13 @@ npm run test:all
|
||||
# Single test file (Node.js native test runner — most tests use this)
|
||||
node --import tsx/esm --test tests/unit/your-file.test.ts
|
||||
|
||||
# Only the unit tests impacted by your change (same TIA selector as the CI gate, #8084)
|
||||
npm run test:scoped # changes in the last commit (or the working tree)
|
||||
npm run test:scoped:staged # staged changes only — pairs well with a pre-commit run
|
||||
npm run test:scoped:full # rebuild the import-graph map first (after adding/moving files)
|
||||
# Exit 1 + "run the full suite" means a hub file (tsconfig, package.json, …) or an
|
||||
# unmapped source changed — the selector fails safe, it never silently skips.
|
||||
|
||||
# Vitest (MCP server, autoCombo, cache)
|
||||
npm run test:vitest
|
||||
|
||||
@@ -301,7 +320,7 @@ src/ # TypeScript (.ts / .tsx)
|
||||
open-sse/ # @omniroute/open-sse workspace
|
||||
├── executors/ # 89 executor implementation modules
|
||||
├── handlers/ # 11 request handlers (chat, responses, embeddings, images, etc.)
|
||||
├── mcp-server/ # MCP server (107 unique tools, 3 transports, 32 scopes)
|
||||
├── mcp-server/ # MCP server (110 unique tools, 3 transports, 33 scopes)
|
||||
├── services/ # 178 top-level services (combo, autoCombo, rateLimitManager, etc.)
|
||||
├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
|
||||
├── transformer/ # Responses API transformer
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# ── Multi-stage Dockerfile for Native Bun Runtime (web-latest-bun) ───────────
|
||||
FROM oven/bun:1.3.14-slim AS base
|
||||
FROM oven/bun:1.4.0-slim AS base
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update \
|
||||
@@ -58,7 +58,7 @@ ENV NODE_ENV=production
|
||||
RUN bun run --quiet build
|
||||
|
||||
# ── Runner Base stage (100% Bun Native Production Runtime) ──────────────────
|
||||
FROM oven/bun:1.3.14-slim AS runner-base
|
||||
FROM oven/bun:1.4.0-slim AS runner-base
|
||||
|
||||
LABEL org.opencontainers.image.title="omniroute" \
|
||||
org.opencontainers.image.description="Unified AI proxy — route any LLM through one endpoint (Bun Native)" \
|
||||
|
||||
60
README.md
60
README.md
@@ -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 15–95% 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 → 354 providers — 150+ free — through one endpoint. Claude Code, Codex, Cursor, Cline, Copilot & Antigravity into FREE Claude / GPT / Gemini with auto-fallback. RTK + Caveman stacked compression saves 15–95% tokens (~89% avg) — never hit limits. 354 AI providers · 150+ free tiers · ~1.51B free tokens/mo · 19 routing strategies · $0 to start."/>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -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 **445 free-tier entries across 39 recurring pool keys** and computes the token headline from the **20 pools with a published positive monthly budget**, deduplicated by shared pool. 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 **446 free-tier entries across 38 recurring pool keys** and computes the token headline from the **20 pools with a published positive monthly budget**, deduplicated by shared pool. 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.51B free tokens per month steady, up to ~2.13B in the first month with signup credits, from 39 documented recurring pool keys covering 445 cataloged free-tier entries behind one endpoint. Honest pool-deduped math — each shared pool counted once, including 20 recurring pools with a published positive monthly token budget; 13 providers are marked avoid in the terms-risk catalog so you decide. Budget bar includes Mistral 1B, LLM7 150M, Nara 150M, Gemini 60M 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.51B free tokens per month steady, up to ~2.13B in the first month with signup credits, from 38 documented recurring pool keys covering 446 cataloged free-tier entries behind one endpoint. Honest pool-deduped math — each shared pool counted once, including 20 recurring pools with a published positive monthly token budget; 13 providers are marked avoid in the terms-risk catalog so you decide. Budget bar includes Mistral 1B, LLM7 150M, Nara 150M, Gemini 60M 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)**.
|
||||
>
|
||||
@@ -49,11 +49,11 @@
|
||||
|
||||
[](https://discord.gg/U47eFqAXCn)
|
||||
[](https://t.me/omnirouteOficial)
|
||||
[](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
|
||||
[](https://chat.whatsapp.com/LTSpdFhXTxjH4R6CCNiKWz)
|
||||
[](https://chat.whatsapp.com/FvuCbrpZmQ6I85n2vW5QIC?s=cl&p=a&mlu=4)
|
||||
[](https://chat.whatsapp.com/KWgatljAjmbELQory59Oti?s=cl&p=a&mlu=4)
|
||||
[](https://omniroute.online)
|
||||
|
||||
**Questions, provider tips, roadmap & support → [Discord](https://discord.gg/U47eFqAXCn) · [Telegram](https://t.me/omnirouteOficial) · WhatsApp [🌍 Global](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) / [🇧🇷 Brasil](https://chat.whatsapp.com/LTSpdFhXTxjH4R6CCNiKWz)**
|
||||
**Questions, provider tips, roadmap & support → [Discord](https://discord.gg/U47eFqAXCn) · [Telegram](https://t.me/omnirouteOficial) · WhatsApp [🌍 Global](https://chat.whatsapp.com/FvuCbrpZmQ6I85n2vW5QIC?s=cl&p=a&mlu=4) / [🇧🇷 Brasil](https://chat.whatsapp.com/KWgatljAjmbELQory59Oti?s=cl&p=a&mlu=4) / [Portal](https://portal.sthub.com.br/communities/groups/st-hub/channels/Omniroute-World-8kRjmK)**
|
||||
|
||||
<br/>
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
|
||||
| | v3.8.49 | **v3.8.50** | `v3.8.51+` |
|
||||
| ------------------------- | :-----: | :-----------------------: | :---------: |
|
||||
| 🌐 Providers | 290 | **350** | more queued |
|
||||
| 🌐 Providers | 290 | **352** | more queued |
|
||||
| 🧠 Unique chat model IDs | 1185 | **1312** | — |
|
||||
| 🖼️ Modality Bridge | — | 🆕 vision + audio + video | — |
|
||||
| 📡 Radar free catalog | — | 🆕 opt-in | — |
|
||||
@@ -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 354 providers. Automatic fallback keeps routing while another healthy target is available. Six pillars: resilient fallback across 354 providers · up to 95% token savings on eligible workloads · $0 to start with 150+ free tiers and 53 recurring/keyless free-forever providers · 36 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/>
|
||||
@@ -332,6 +332,8 @@ No combo to create. Set your model to `auto` (or a variant) and OmniRoute builds
|
||||
<tr><td align="left" nowrap><code>auto/cheap</code></td><td align="left">💰 Cheapest per token first</td></tr>
|
||||
<tr><td align="left" nowrap><code>auto/offline</code></td><td align="left">🔋 Most quota / rate-limit headroom first</td></tr>
|
||||
<tr><td align="left" nowrap><code>auto/smart</code></td><td align="left">🔭 Quality-first + 10% exploration to discover better models</td></tr>
|
||||
<tr><td align="left" nowrap><code>auto/lkgp</code></td><td align="left">📌 Explicit last-known-good-provider stickiness</td></tr>
|
||||
<tr><td align="left" nowrap><code>auto/chaos</code></td><td align="left">🧪 Fault-injection weights for resilience testing (chaos engineering)</td></tr>
|
||||
</table>
|
||||
|
||||
##
|
||||
@@ -429,7 +431,7 @@ All **19** strategies — mix & match per combo step:
|
||||
<tr>
|
||||
<td align="center">17</td>
|
||||
<td nowrap><code>auto</code></td>
|
||||
<td>15-factor live scoring across every connection 🤖</td>
|
||||
<td>16-factor live scoring across every connection 🤖</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">18</td>
|
||||
@@ -443,13 +445,13 @@ All **19** strategies — mix & match per combo step:
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<sub>The Auto-Combo engine scores every candidate on **15 factors** (health, quota, cost, latency, task fit, quality, session availability…) — see [`docs/routing/AUTO-COMBO.md`](docs/routing/AUTO-COMBO.md).</sub>
|
||||
<sub>The Auto-Combo engine scores every candidate on **16 factors** (health, quota, cost, latency, task fit, quality, session availability…) — see [`docs/routing/AUTO-COMBO.md`](docs/routing/AUTO-COMBO.md).</sub>
|
||||
|
||||
##
|
||||
|
||||
### 🧱 Resilience is built in (3 independent layers)
|
||||
|
||||
<img src="./docs/diagrams/resilience-layers.svg" width="100%" alt="OmniRoute resilience — 3 independent self-healing layers, the right layer for the right failure. Layer 1 provider circuit breaker (whole provider): trips only on 408/5xx, thresholds OAuth 10× / API-key 15× / local 2×, resets 60s/30s/15s into a HALF-OPEN probe, lazy recovery; while OPEN the combo reroutes to the next provider. Layer 2 connection cooldown (one key/account): base 5s OAuth / 3s API-key, exponential ×2 backoff with anti-thundering-herd guard, 429 honors Retry-After, success clears all error state; one cooling key is skipped while sibling keys keep serving. Layer 3 model lockout (one model): per-model 429, local 404 or mode denials lock just that model — never the whole connection. Terminal states (banned, expired, credits exhausted) are for the operator, not cooldowns."/>
|
||||
<img src="./docs/diagrams/resilience-layers.svg" width="100%" alt="OmniRoute resilience — 3 independent self-healing layers, the right layer for the right failure. Layer 1 provider circuit breaker (whole provider): trips only on 408/5xx, thresholds OAuth 8× / API-key 12× / local 2×, resets 60s/30s/15s into a HALF-OPEN probe, lazy recovery; while OPEN the combo reroutes to the next provider. Layer 2 connection cooldown (one key/account): base 5s OAuth / 3s API-key, exponential ×2 backoff with anti-thundering-herd guard, 429 honors Retry-After, success clears all error state; one cooling key is skipped while sibling keys keep serving. Layer 3 model lockout (one model): per-model 429, local 404 or mode denials lock just that model — never the whole connection. Terminal states (banned, expired, credits exhausted) are for the operator, not cooldowns."/>
|
||||
|
||||
<sub>📖 [Auto-Combo Engine](docs/routing/AUTO-COMBO.md) · [Resilience Guide](docs/architecture/RESILIENCE_GUIDE.md)</sub>
|
||||
|
||||
@@ -461,7 +463,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: 354 providers, 150+ 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 & per-feature detail vs 9router, OpenRouter, CLIProxyAPI & LiteLLM → [`docs/comparison/OMNIROUTE_VS_ALTERNATIVES.md`](docs/comparison/OMNIROUTE_VS_ALTERNATIVES.md)</sub>
|
||||
|
||||
@@ -548,7 +550,7 @@ the current catalog at **[radar.omniroute.online/planos](https://radar.omniroute
|
||||
- **🗜️ Compression hardening** — default-on inflation guard, Caveman packs for DE / FR / JA + Chinese (wényán), RTK filters for Gradle & .NET. → [Compression](docs/compression/COMPRESSION_ENGINES.md)
|
||||
- **💸 Honest flat-rate cost** — subscription / coding-plan providers read **$0** in cost analytics; budget, quota & routing keep estimating. → [API Reference](docs/reference/API_REFERENCE.md)
|
||||
- **⚖️ Quota-Share routing** — split a shared account's quota fairly across pooled keys, work-conserving so idle slices are lent out. → [Resilience Guide](docs/architecture/RESILIENCE_GUIDE.md)
|
||||
- **🤖 One-command CLI/agent setup** — 12 registered `setup-*` commands; `omniroute run` launches 7 CLIs (Claude Code, Codex, Aider, Goose, OpenCode, Qwen Code, Gemini CLI); `omniroute configure` supports 9 targets with an interactive provider+model picker and per-context favorites. → [CLI Integrations](docs/guides/CLI-INTEGRATIONS.md)
|
||||
- **🤖 One-command CLI/agent setup** — 13 registered `setup-*` commands; `omniroute run` launches 7 CLIs (Claude Code, Codex, Aider, Goose, OpenCode, Qwen Code, Gemini CLI); `omniroute configure` supports 10 targets with an interactive provider+model picker and per-context favorites. → [CLI Integrations](docs/guides/CLI-INTEGRATIONS.md)
|
||||
- **🛰️ Remote mode** — drive a remote OmniRoute with scoped tokens (`connect` / `contexts` / `tokens`) + an `antigravity` OAuth helper for VPS installs. → [Remote Mode](docs/guides/REMOTE-MODE.md)
|
||||
- **🧭 Smarter auto-routing** — `auto/<category>:<tier>` combos, **Fusion** (model panel + judge), task-aware routing, per-request model / mode / USD-budget overrides. → [Auto-Combo](docs/routing/AUTO-COMBO.md)
|
||||
- **🗜️ Pluggable compression** — 12 composable engines + Compression Studios: LLMLingua-2, two-tier Ultra, omniglyph, per-step fidelity gate, GCF v3.2, drag-reorder editor. → [Compression](docs/compression/COMPRESSION_ENGINES.md)
|
||||
@@ -559,9 +561,10 @@ the current catalog at **[radar.omniroute.online/planos](https://radar.omniroute
|
||||
- **🖼️ New endpoints** — `/v1/ocr` (Mistral OCR) and `/v1/audio/translations` (Whisper-style) round out the media surface. → [API Reference](docs/reference/API_REFERENCE.md)
|
||||
- **🎨 Image / video / audio generation** — one API for media: xAI Grok Imagine & Novita AI video, ComfyUI, Magnific, Adobe Firefly, Segmind, and speech providers such as ElevenLabs. → [API Reference](docs/reference/API_REFERENCE.md)
|
||||
- **🌍 Deployment & ops** — reverse-proxy `basePath`, browser-language auto-detect, per-key device tracking, root-less MITM trust, zh-TW localization. → [Environment](docs/reference/ENVIRONMENT.md)
|
||||
- **🤝 More providers & agents** — Cursor Cloud Agent, Grok Build (xAI) with browser + OAuth login, Ollama first-class card, Claude Opus 5 & Sonnet 5, Kimi official partnership (Code/Web/Moonshot), Zed, Requesty, SenseNova, Yuanbao, Agnes AI… and a refreshed **351-provider catalog**. → [Providers](docs/reference/PROVIDER_REFERENCE.md)
|
||||
- **🤝 More providers & agents** — cloud agents (Codex Cloud, Cursor, Devin, Jules), Grok Build (xAI) with browser + OAuth login, Ollama first-class card, Claude Opus 5 & Sonnet 5, Kimi official partnership (Code/Web/Moonshot), Zed, Requesty, SenseNova, Yuanbao, Agnes AI… and a refreshed **352-provider catalog**. → [Providers](docs/reference/PROVIDER_REFERENCE.md)
|
||||
- **📡 Routing transparency** — every response carries an `X-OmniRoute-Decision` header naming the strategy/provider/latency that served it, a new `cache-optimized` combo strategy + Auto-Combo `cacheAffinity` factor route repeat requests back to the connection holding the cached prefix, and a read-only `/v1/auto-combo/{channel}/candidates` endpoint exposes an `auto/*` channel's live candidate pool. → [Auto-Combo](docs/routing/AUTO-COMBO.md)
|
||||
- **⚡ Local performance & infra** — one-click local Redis, Cloudflare Workers / Deno Deploy relay deployers, Bifrost & Mux as supervised embedded services. → [Embedded Services](docs/frameworks/EMBEDDED-SERVICES.md)
|
||||
- **🧩 Also in the box** — plugin framework + marketplace, Omni/Agent/GitHub skills frameworks, Obsidian vault integration (22 MCP tools), OpenAI-compatible Batch & Files APIs, semantic response cache, gamification with leaderboards, ACP agent discovery (15 built-in agents), scheduled log export to BigQuery, `auto/chaos` fault injection, a Telegram bot bridge, an in-app version manager and LMArena-ELO free-provider rankings. → [Docs](docs/README.md)
|
||||
|
||||
<br/>
|
||||
|
||||
@@ -631,7 +634,7 @@ omniroute run qwen --model glm/glm-5.2 -- -p "reply OK"
|
||||
omniroute run gemini --model glm/glm-5.2 -- --skip-trust -p "reply OK"
|
||||
|
||||
# Or pick provider+model interactively and write the tool's own config:
|
||||
omniroute configure codex # also: claude opencode qwen aider goose cline continue kilo
|
||||
omniroute configure codex # also: claude opencode qwen aider goose gemini cline continue kilo
|
||||
```
|
||||
|
||||
Every command honors the active remote context (`omniroute connect <host>`), `--dry-run`
|
||||
@@ -642,11 +645,11 @@ of your shell history. → [CLI Integrations](docs/guides/CLI-INTEGRATIONS.md)
|
||||
|
||||
<div align="center">
|
||||
|
||||
## 🌐 352 AI Providers — 154 Catalog-Marked Free
|
||||
## 🌐 352 AI Providers — 152 Catalog-Marked Free
|
||||
|
||||
</div>
|
||||
|
||||
> **351 registered providers** across the canonical chat, media, search, local, cloud-agent and system collections, including **154 carrying `hasFree: true` discovery metadata**. The chat model registry covers **268 providers / 2,566 distinct provider-model pairs / 1,312 raw model IDs**; the separate free-budget catalog has **455 per-model rows**, **40 recurring pools** and **56 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 **446 per-model rows**, **38 recurring pools** and **53 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">
|
||||
|
||||
@@ -810,7 +813,7 @@ Tokens are scoped `read` / `write` / `admin`; process-spawning routes stay loopb
|
||||
|
||||
<div align="left">
|
||||
|
||||
<img src="./docs/diagrams/cli-terminal.svg" width="50%" alt="Animated terminal demoing the OmniRoute CLI — omniroute providers list, omniroute combo list and omniroute health — cycling over the 85-command top-level surface: providers · oauth · keys · combo · nodes · models · cache · compression · cost · usage · quota · health · resilience · telemetry · logs · audit · mcp · a2a · cloud · memory · skills · eval · tunnel · backup · sync · webhooks · policy · pricing · translator · simulate …"/>
|
||||
<img src="./docs/diagrams/cli-terminal.svg" width="50%" alt="Animated terminal demoing the OmniRoute CLI — omniroute providers list, omniroute combo list and omniroute health — cycling over the 86-command top-level surface: providers · oauth · keys · combo · nodes · models · cache · compression · cost · usage · quota · health · resilience · telemetry · logs · audit · mcp · a2a · cloud · memory · skills · eval · tunnel · backup · sync · webhooks · policy · pricing · translator · simulate …"/>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -821,11 +824,11 @@ Expose OmniRoute over **MCP**, **A2A**, a **REST API**, **webhooks** or a **remo
|
||||
<table>
|
||||
<tr><th align="left">Interface</th><th align="left">Endpoint / command</th><th align="left">Use it for</th></tr>
|
||||
<tr><td align="left" nowrap>🧰 <b>MCP (stdio)</b></td><td align="left" nowrap><code>omniroute --mcp</code></td><td align="left">Plug into Claude Desktop, Cursor, any MCP client</td></tr>
|
||||
<tr><td align="left" nowrap>🌊 <b>MCP (HTTP)</b></td><td align="left" nowrap><code>/api/mcp/stream</code></td><td align="left">Remote MCP — <b>110 tools</b>, 33 scopes, full audit trail</td></tr>
|
||||
<tr><td align="left" nowrap>🌊 <b>MCP (HTTP)</b></td><td align="left" nowrap><code>/api/mcp/stream</code></td><td align="left">Remote MCP — <b>110 tools</b>, 33 scopes (enforcement opt-in), full audit trail</td></tr>
|
||||
<tr><td align="left" nowrap>📡 <b>MCP (SSE)</b></td><td align="left" nowrap><code>/api/mcp/sse</code></td><td align="left">Streaming MCP transport</td></tr>
|
||||
<tr><td align="left" nowrap>🤝 <b>A2A</b></td><td align="left" nowrap><code>/.well-known/agent.json</code></td><td align="left">Agent-to-agent, <b>JSON-RPC 2.0</b> + SSE, 6 skills</td></tr>
|
||||
<tr><td align="left" nowrap>🌐 <b>REST API</b></td><td align="left" nowrap><code>/v1/*</code></td><td align="left">OpenAI-compatible — chat, embeddings, images, audio, OCR</td></tr>
|
||||
<tr><td align="left" nowrap>🔔 <b>Webhooks</b></td><td align="left" nowrap><code>/api/webhooks</code></td><td align="left">Push events (usage, quota, errors, routing) to your URL</td></tr>
|
||||
<tr><td align="left" nowrap>🔔 <b>Webhooks</b></td><td align="left" nowrap><code>/api/webhooks</code></td><td align="left">Push request / quota events to Slack, Discord, Telegram or any URL</td></tr>
|
||||
<tr><td align="left" nowrap>🛰️ <b>Remote CLI</b></td><td align="left" nowrap><code>omniroute connect <host></code></td><td align="left">Drive a remote instance with scoped access tokens</td></tr>
|
||||
</table>
|
||||
|
||||
@@ -917,6 +920,8 @@ The 12 engines above shrink what goes **in**. Three more layers shape **how**, *
|
||||
- **🪄 Output Styles** _(output-axis steering)_ — inject deterministic, cache-safe response-shaping instructions; combinable, each at `lite` / `full` / `ultra` intensity. Adding a style is a one-line registry entry:
|
||||
- **Terse prose** — drop filler / articles / hedging; keep technical substance exact.
|
||||
- **Less code** — "lazy senior dev" YAGNI: smallest working change, no unrequested scaffolding.
|
||||
- **Ponytail (lazy senior dev)** — climb the YAGNI ladder, fix the root cause, smallest working diff.
|
||||
- **I have ADHD (action-first)** — next action leads, steps numbered, one concrete next step, no preamble.
|
||||
- **Terse CJK (文言)** — classical-Chinese ultra-terse style (locale-gated to `zh`).
|
||||
- **🎯 Adaptive context-budget** _(the dial)_ — instead of one on/off token threshold, escalate the cheapest, most-lossless engines only as far as needed to **fit the model's context window**. Policy: `reserve-output` (default, model-aware) · `percentage` · `absolute`. Mode: `floor` (guarantee fit) · `replace-autotrigger` (your explicit choice wins) · `off` (legacy threshold).
|
||||
- **🎛️ Where compression is decided** _(precedence, high → low)_ — per-request `x-omniroute-compression` header › routing-combo override › active named profile › adaptive / auto-trigger › panel default › off. The applied plan echoes back in the `X-OmniRoute-Compression: <mode>; source=<source>` response header.
|
||||
@@ -1015,7 +1020,7 @@ Full table: [Docker Guide — runtime RAM](docs/guides/DOCKER_GUIDE.md#runtime-r
|
||||
Standard `bun install` and global installation (`bun install -g omniroute`) are supported via Bun runtime detection:
|
||||
|
||||
- **Built-in `bun:sqlite`**: OmniRoute uses Bun's built-in `bun:sqlite` driver when running under Bun, falling back to `better-sqlite3` on Node.js or `sql.js`.
|
||||
- **Automatic Webpack bundler selection**: Development (`bun run dev`) and production builds (`bun run build`) automatically detect Bun and disable Turbopack in favor of Webpack to prevent native V8 binding incompatibilities.
|
||||
- **Automatic Webpack bundler selection in dev**: Development (`bun run dev`) automatically detects Bun and disables Turbopack in favor of Webpack to prevent native V8 binding incompatibilities. Production builds (`bun run build`) follow `OMNIROUTE_USE_TURBOPACK` exactly as on Node: Turbopack by default, `OMNIROUTE_USE_TURBOPACK=0` to build with Webpack (`Dockerfile.bun` exposes it as a `--build-arg`).
|
||||
- **Dedicated Bun Dockerfile**: Multi-stage `Dockerfile.bun` for native Bun production deployments (`docker build -f Dockerfile.bun -t omniroute:bun .`).
|
||||
|
||||
```bash
|
||||
@@ -1178,9 +1183,10 @@ Métricas canônicas em 2026-08-24: **1.029 vídeos únicos** · **11.132.922 vi
|
||||
| 🐙 **GitHub** — follow for releases & tips | [@diegosouzapw](https://github.com/diegosouzapw) |
|
||||
| 💬 **Discord** | [discord.gg/U47eFqAXCn](https://discord.gg/U47eFqAXCn) |
|
||||
| ✈️ **Telegram** | [t.me/omnirouteOficial](https://t.me/omnirouteOficial) |
|
||||
| 🟢 **WhatsApp — 🌍 Global** | [join the group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) |
|
||||
| 🟢 **WhatsApp — 🇧🇷 Brasil** | [entrar no grupo](https://chat.whatsapp.com/LTSpdFhXTxjH4R6CCNiKWz) |
|
||||
| 🟢 **WhatsApp — 🌍 Global** | [join the group](https://chat.whatsapp.com/FvuCbrpZmQ6I85n2vW5QIC?s=cl&p=a&mlu=4) |
|
||||
| 🟢 **WhatsApp — 🇧🇷 Brasil** | [entrar no grupo](https://chat.whatsapp.com/KWgatljAjmbELQory59Oti?s=cl&p=a&mlu=4) |
|
||||
| 🌍 **Website** | [omniroute.online](https://omniroute.online) |
|
||||
| 🌍 **🌍StHub OmniRoute Community (free)** | [portal sthub](https://portal.sthub.com.br/communities/groups/st-hub/channels/Omniroute-World-8kRjmK) |
|
||||
| 📦 **Source code** | [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute) |
|
||||
| 🐛 **Report a bug** | [open an issue](https://github.com/diegosouzapw/OmniRoute/issues) — attach `npm run system-info` output |
|
||||
| 🤝 **Contribute** | [CONTRIBUTING.md](CONTRIBUTING.md) · [Branching & Release Model](docs/ops/BRANCHING_MODEL.md) · pick a `good first issue` |
|
||||
@@ -1202,7 +1208,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>>=22.22.2 <23 || >=24.0.0 <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) — 120 domain modules, 167 migrations</td></tr>
|
||||
<tr><td nowrap><b>Database</b></td><td>better-sqlite3 (SQLite, WAL journaling) + LowDB (JSON legacy) — 122 domain modules, 167 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>
|
||||
@@ -1263,9 +1269,9 @@ Métricas canônicas em 2026-08-24: **1.029 vídeos únicos** · **11.132.922 vi
|
||||
<tr><td nowrap><b><a href="docs/compression/COMPRESSION_RULES_FORMAT.md">Compression Rules Format</a></b></td><td>JSON rule-pack schemas for Caveman and RTK filters</td></tr>
|
||||
<tr><td nowrap><b><a href="docs/compression/COMPRESSION_LANGUAGE_PACKS.md">Compression Language Packs</a></b></td><td>Language detection and Caveman rule-pack authoring</td></tr>
|
||||
<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>15-factor scoring, mode packs, self-healing</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: 39 documented recurring pools / 445 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: 38 documented recurring pools / 446 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>
|
||||
@@ -1666,7 +1672,7 @@ MIT License - see [LICENSE](LICENSE) for details.
|
||||
|
||||
**[⬆ Back to top](#-omniroute)** · Built with ❤️ for the open-source AI community.
|
||||
|
||||
<sub>OmniRoute v3.8.50 · Node ≥22.22.2 · MIT License · <a href="https://omniroute.online">omniroute.online</a></sub>
|
||||
<sub>OmniRoute v3.8.51 · Node ≥22.22.2 · MIT License · <a href="https://omniroute.online">omniroute.online</a></sub>
|
||||
|
||||
</div>
|
||||
<!-- GitHub Discussions enabled for community Q&A -->
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
## codex-chatgpt-web
|
||||
|
||||
Parts of `open-sse/vendor/codex-chatgpt-web/` are adapted from
|
||||
[`miuuyy/codex-chatgpt-web`](https://github.com/miuuyy/codex-chatgpt-web), commit
|
||||
`55592fca0ba19a27f1b769cec8fff61ff340a785`.
|
||||
[`miuuyy/codex-chatgpt-web`](https://github.com/miuuyy/codex-chatgpt-web), v4.0.7 commit
|
||||
`b59d7dc51b84fb1f465ff1d00f5207f3b2b4a494`.
|
||||
|
||||
MIT License
|
||||
|
||||
|
||||
@@ -32,17 +32,20 @@ export function resolveChatGptWebCodexMcpEntry(rootDir = root, exists = existsSy
|
||||
return candidates.find((candidate) => exists(candidate)) ?? null;
|
||||
}
|
||||
|
||||
export async function loadChatGptWebCodexMcpModule(entry) {
|
||||
if (entry.endsWith(".ts")) {
|
||||
await import("tsx/esm");
|
||||
}
|
||||
return import(pathToFileURL(entry).href);
|
||||
}
|
||||
|
||||
export async function startChatGptWebCodexMcp(args = process.argv.slice(2), rootDir = root) {
|
||||
const socketIndex = args.indexOf("--broker-socket");
|
||||
const brokerSocketPath = socketIndex >= 0 ? args[socketIndex + 1] : undefined;
|
||||
if (!brokerSocketPath) throw new Error("--broker-socket is required");
|
||||
const entry = resolveChatGptWebCodexMcpEntry(rootDir);
|
||||
if (!entry) throw new Error("ChatGPT Web (Codex) MCP entrypoint was not found");
|
||||
if (entry.endsWith(".ts")) {
|
||||
const { register } = await import("node:module");
|
||||
register("tsx/esm", pathToFileURL(`${rootDir}/`));
|
||||
}
|
||||
const module = await import(pathToFileURL(entry).href);
|
||||
const module = await loadChatGptWebCodexMcpModule(entry);
|
||||
await module.runChatGptMcpServer({ brokerSocketPath });
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,11 @@ 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 { ServerSupervisor, detectMitmCrash } from "../runtime/processSupervisor.mjs";
|
||||
import {
|
||||
ServerSupervisor,
|
||||
detectMitmCrash,
|
||||
BUN_PRELOAD_PATH,
|
||||
} from "../runtime/processSupervisor.mjs";
|
||||
import { isTermux } from "../../../scripts/build/postinstallSupport.mjs";
|
||||
import {
|
||||
ensureAndroidCacheDir,
|
||||
@@ -306,7 +310,7 @@ function runDaemon(serverJs, env, memoryLimit, dashboardPort, apiPort) {
|
||||
process.versions.bun ? process.execPath : "node",
|
||||
[
|
||||
...(process.versions.bun
|
||||
? ["--preload", join(APP_DIR, "open-sse/utils/setupPolyfill.ts")]
|
||||
? ["--preload", BUN_PRELOAD_PATH]
|
||||
: buildNodeHeapArgs(process.env, memoryLimit)),
|
||||
serverJs,
|
||||
],
|
||||
@@ -331,7 +335,7 @@ function runWithoutRecovery(serverJs, env, memoryLimit, dashboardPort, apiPort,
|
||||
process.versions.bun ? process.execPath : "node",
|
||||
[
|
||||
...(process.versions.bun
|
||||
? ["--preload", join(APP_DIR, "open-sse/utils/setupPolyfill.ts")]
|
||||
? ["--preload", BUN_PRELOAD_PATH]
|
||||
: buildNodeHeapArgs(process.env, memoryLimit)),
|
||||
serverJs,
|
||||
],
|
||||
@@ -423,7 +427,9 @@ async function runWithSupervisor(
|
||||
if (detectMitmCrash(crashLog)) {
|
||||
try {
|
||||
const PROJECT_ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "..");
|
||||
const { updateSettings } = await import(pathToFileURL(join(PROJECT_ROOT, "src/lib/db/settings.ts")).href);
|
||||
const { updateSettings } = await import(
|
||||
pathToFileURL(join(PROJECT_ROOT, "src/lib/db/settings.ts")).href
|
||||
);
|
||||
updateSettings({ mitmEnabled: false });
|
||||
} catch {}
|
||||
return "disable-mitm-and-retry";
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { spawn } from "node:child_process";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { writePidFile, cleanupPidFile, killAllSubprocesses, isPidRunning } from "../utils/pid.mjs";
|
||||
import {
|
||||
RESTART_RESET_MS,
|
||||
@@ -17,6 +18,24 @@ import {
|
||||
|
||||
const CRASH_LOG_LINES = 50;
|
||||
|
||||
const PACKAGE_ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "..");
|
||||
// Bun needs the Node-compat polyfill preloaded (#9761). The file ships at the
|
||||
// package root via package.json "files" (see scripts/build/pack-artifact-policy.ts)
|
||||
// and is never copied into dist/, so the path must resolve against the package
|
||||
// root — resolving it next to the server bundle fails with "preload not found" (#11980).
|
||||
export const BUN_PRELOAD_PATH = join(PACKAGE_ROOT, "open-sse", "utils", "setupPolyfill.ts");
|
||||
|
||||
/**
|
||||
* Argument vector for the server child. Kept pure so tests can assert on it
|
||||
* directly: the bare `import { spawn }` above cannot be intercepted without
|
||||
* --experimental-test-module-mocks (same seam as #8131).
|
||||
*/
|
||||
export function buildServerSpawnArgs(serverPath, memoryLimit, env = process.env) {
|
||||
return process.versions.bun
|
||||
? ["--preload", BUN_PRELOAD_PATH, serverPath]
|
||||
: buildNodeRuntimeArgs(env, memoryLimit, serverPath);
|
||||
}
|
||||
|
||||
export class ServerSupervisor {
|
||||
constructor({
|
||||
serverPath,
|
||||
@@ -55,21 +74,11 @@ export class ServerSupervisor {
|
||||
// Node args come from buildNodeRuntimeArgs (#9209 IPv4-first DNS + #5238
|
||||
// heap flag handling); the Bun branch keeps #9761's polyfill preload —
|
||||
// Bun does not accept the Node-only flags.
|
||||
this.child = spawn(
|
||||
process.execPath,
|
||||
process.versions.bun
|
||||
? [
|
||||
"--preload",
|
||||
join(dirname(this.serverPath), "open-sse/utils/setupPolyfill.ts"),
|
||||
this.serverPath,
|
||||
]
|
||||
: buildNodeRuntimeArgs(process.env, this.memoryLimit, this.serverPath),
|
||||
{
|
||||
cwd: dirname(this.serverPath),
|
||||
env: this.env,
|
||||
stdio: showLog ? "inherit" : ["ignore", "pipe", "pipe"],
|
||||
}
|
||||
);
|
||||
this.child = spawn(process.execPath, buildServerSpawnArgs(this.serverPath, this.memoryLimit), {
|
||||
cwd: dirname(this.serverPath),
|
||||
env: this.env,
|
||||
stdio: showLog ? "inherit" : ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
|
||||
writePidFile("server", this.child.pid);
|
||||
|
||||
|
||||
1
changelog.d/features/11783-react-compiler.md
Normal file
1
changelog.d/features/11783-react-compiler.md
Normal file
@@ -0,0 +1 @@
|
||||
- **feat(ui):** enable React Compiler (`reactCompiler: true` + `babel-plugin-react-compiler`) for automatic memoization at build time ([#11783](https://github.com/diegosouzapw/OmniRoute/pull/11783)) — thanks @jonlwheat2-gif
|
||||
@@ -0,0 +1 @@
|
||||
- **feat(sse):** treat `max` as a first-class reasoning-effort tier and clamp per model family (GLM 5.1+/DeepSeek V4+/Kimi K3+ keep native `max`; o1/MiniMax/Grok/Muse Spark clamp to their upstream ceiling) ([#11875](https://github.com/diegosouzapw/OmniRoute/pull/11875)) — thanks @Chewji9875
|
||||
@@ -0,0 +1 @@
|
||||
- **feat(routing):** add a `score` Auto router strategy that selects the highest configured weighted score and reuses `explorationRate`.
|
||||
@@ -0,0 +1 @@
|
||||
- Add a runtime feature flag to disable universal context handoffs globally without changing the default behavior.
|
||||
1
changelog.d/features/12214-usage-supported-capability.md
Normal file
1
changelog.d/features/12214-usage-supported-capability.md
Normal file
@@ -0,0 +1 @@
|
||||
- **feat(providers):** the provider plugin manifest now also advertises a `usage-supported` capability for the 46 providers whose usage API is accepted by the server and Dashboard routes, so integrators can distinguish "the server will serve quota for this provider" from "a fetcher is wired" without reading TypeScript. Discovery only — no fetcher or quota change. `usage-fetch` resolves on id or alias (the usage dispatcher accepts both); `usage-supported` resolves on id alone, matching the runtime guard `USAGE_SUPPORTED_PROVIDERS.includes(providerId)`. `USAGE_SUPPORTED_PROVIDERS` moved to a zero-dependency leaf (`open-sse/services/usage/supportedProviders.ts`) and is re-exported from `providers.ts`, mirroring the `fetcherProviders` leaf from #11903 and keeping the manifest a light module. ([#12214](https://github.com/diegosouzapw/OmniRoute/pull/12214)) — thanks @maxmad64bis
|
||||
1
changelog.d/features/12218-rankings-reliability-sort.md
Normal file
1
changelog.d/features/12218-rankings-reliability-sort.md
Normal file
@@ -0,0 +1 @@
|
||||
- **feat(rankings):** order Free Provider Rankings by what each provider actually served — `GET /api/free-provider-rankings?sortBy=reliability` and a "Most reliable first" toggle on the page. Providers with too few calls to state a success rate keep their score order below the measured ones; the default order is unchanged ([#12218](https://github.com/diegosouzapw/OmniRoute/pull/12218)).
|
||||
@@ -0,0 +1 @@
|
||||
- **perf(sse):** defer `cloneLogPayload()` in the structured SSE collector until after the `maxEvents`/`maxBytes` cap check, eliminating ~9,800 wasted `structuredClone` calls per streaming response (65–71% faster `push()`). Reducer snapshot isolation restored for OpenAI and Responses summaries ([#12241](https://github.com/diegosouzapw/OmniRoute/pull/12241)) — thanks @PauloHSOliveira
|
||||
@@ -0,0 +1 @@
|
||||
- **feat(usage):** Devin CLI agentic quota (Codeium seat-management GetUserStatus) and OpenRouter key limits plus account credits now surface in Provider Limits ([#12256](https://github.com/diegosouzapw/OmniRoute/pull/12256) — thanks @Neuron-Mr-White)
|
||||
1
changelog.d/features/12317-reliability-scoring-factor.md
Normal file
1
changelog.d/features/12317-reliability-scoring-factor.md
Normal file
@@ -0,0 +1 @@
|
||||
- **feat(auto-combo):** Auto-Combo scoring can now weigh how often a provider/model has actually succeeded. The engine already carried that number on every candidate — 24 hours of usage history behind a ten-sample floor, real-time metrics otherwise — and the scoring function never read it, while the weight table described `stability` as if it did. `reliability` (`1 - failureRate`, with the same field precedence and the same rate-bounding the speed ranking already uses, so a corrupt reading means "nothing observed" rather than "fails every call") is now a declared factor shipping at weight `0`, so routing is unchanged until an operator gives it one, and the `stability` description now matches what that factor computes ([#12317](https://github.com/diegosouzapw/OmniRoute/pull/12317))
|
||||
@@ -0,0 +1 @@
|
||||
- **feat(routing):** With `freeAccessPolicy: "strict"`, the read-only candidate listing (`GET /v1/auto-combo/{channel}/candidates`) no longer hides the candidates the zero-cost guard excludes — the same read-only transparency the resilience filter already honours (#9133). Each candidate now carries `freeAccessExclusion` saying why it would be kept out, and it tells an exhausted allowance apart from a quota reading that never arrived or went stale, which used to look identical from the outside. Routing is unchanged: the listing reports, it never enforces. The separate `excludeTosAvoid` guard still drops its candidates without a reason; that gap is now documented rather than closed ([#12319](https://github.com/diegosouzapw/OmniRoute/pull/12319))
|
||||
@@ -0,0 +1 @@
|
||||
- **feat(radar):** The Radar catalog table now shows two facts it was already receiving from the feed and dropping on the floor: the per-model rate limits (requests and tokens, per minute and per day) in a new column, and a badge when a provider's terms state it may train on the prompts you send. A limit of zero renders as zero rather than "rate-only" — for a ceiling those are opposite facts — and a model with no training statement gets no badge, because an absent statement is not a guarantee ([#12320](https://github.com/diegosouzapw/OmniRoute/pull/12320))
|
||||
1
changelog.d/features/12342-radar-optin-access-rules.md
Normal file
1
changelog.d/features/12342-radar-optin-access-rules.md
Normal file
@@ -0,0 +1 @@
|
||||
- **feat(radar):** explain Community, single-use, contributor, supporter, recovery, abuse, offers, and privacy rules before either Radar activation action, and remove the superseded fixed-PR grant promise from every UI locale ([#12342](https://github.com/diegosouzapw/OmniRoute/pull/12342))
|
||||
1
changelog.d/features/12377-profile-streak-card.md
Normal file
1
changelog.d/features/12377-profile-streak-card.md
Normal file
@@ -0,0 +1 @@
|
||||
- **feat(gamification):** the dashboard Profile page now shows the real daily streak — `/api/gamification/level` returns `streak: { current, longest }` (per key with `apiKeyId`, operator-wide maximum otherwise) and the streak card reads it instead of a hard-coded 0 (#2403)
|
||||
1
changelog.d/features/12385-leaderboard-api-key-names.md
Normal file
1
changelog.d/features/12385-leaderboard-api-key-names.md
Normal file
@@ -0,0 +1 @@
|
||||
- **feat(gamification):** the dashboard leaderboard now shows each API key's display name under the Name column instead of a truncated key id; `GET /api/gamification/leaderboard` attaches `name` per entry (name only — no key material), while the shared ranking helper and the federation leaderboard stay id-only — thanks @pacocartones
|
||||
@@ -0,0 +1 @@
|
||||
- **feat(gamification):** enforce the documented 1000 XP/min per-API-key anti-cheat rate limit on the XP award path; over-limit awards are logged and skipped instead of persisted, and the sliding window now matches the timestamp format stored in `xp_audit_log` ([#2403](https://github.com/diegosouzapw/OmniRoute/issues/2403))
|
||||
1
changelog.d/features/12401-admin-anomalies-i18n.md
Normal file
1
changelog.d/features/12401-admin-anomalies-i18n.md
Normal file
@@ -0,0 +1 @@
|
||||
- **feat(admin):** localize the gamification anomalies page — the loading state, the Status column and the Suspicious badge now come from the `common` catalog (new `common.suspicious` key propagated to every locale) — add it to the Gamification sidebar group as `gamification-admin` (`/dashboard/gamification/admin`), and expose the loading and empty states as polite `role="status"` live regions (#12401 — thanks @pacocartones)
|
||||
6
changelog.d/features/maxai-provider.md
Normal file
6
changelog.d/features/maxai-provider.md
Normal file
@@ -0,0 +1,6 @@
|
||||
- **feat(providers):** add MaxAI as a signed, OpenAI-compatible provider serving its 13 paid chat models (GPT-5.6 / Luna / Thinking, Claude 5 Sonnet, Claude Haiku 4.5, Gemini 3.1 Pro / Flash-Lite, Grok 4.1-fast / 4.5, DeepSeek V3.2 / R1, Llama 3.3 70B) through OmniRoute's `/v1` endpoint, with per-request HMAC-SHA1→SM3→AES request signing, live model + context-window discovery from `/models/get_config`, and prompted tool-calling translated to OpenAI `tool_calls`
|
||||
- **feat(providers):** MaxAI vision input — image_url content parts are forwarded inline in `message_content` to the 6 vision-capable models (GPT-5.6 / Luna / Thinking, Claude Haiku 4.5, Gemini 3.1 Pro / Flash-Lite)
|
||||
- **feat(providers):** MaxAI image generation — 6 image models (gpt-image-1, dall-e-3, flux-1-schnell/dev/pro, sd3-medium) exposed through `POST /v1/images/generations`
|
||||
- **feat(providers):** MaxAI document RAG — inline base64 file/document attachments are uploaded to MaxAI (content-addressed `doc_id`) and attached to the chat via `doc_list`
|
||||
- **feat(providers):** browserless MaxAI onboarding — email device-pair login (`/api/providers/[id]/login`) and signed access-token refresh, so a connection can be created and kept fresh without a real browser or Google OAuth
|
||||
- **feat(providers):** per-provider TLS impersonation profile (MaxAI presents a Windows Firefox-150 client fingerprint) so its bot-sensitive endpoints accept OmniRoute traffic
|
||||
5
changelog.d/features/orchestration-agents-ws.md
Normal file
5
changelog.d/features/orchestration-agents-ws.md
Normal file
@@ -0,0 +1,5 @@
|
||||
- **feat(dashboard):** the `/dashboard/orchestration` snapshot hook now subscribes to the
|
||||
`agents` WebSocket channel (`agent.task.updated`) instead of `requests` as its refetch
|
||||
trigger, and relaxes its background poll from 5s to 30s while that WS connection is up —
|
||||
falling back to the tighter 5s cadence, reprogrammed live on any connect/disconnect
|
||||
transition, whenever the socket is down.
|
||||
11
changelog.d/features/orchestration-canvas-fase2-quickwins.md
Normal file
11
changelog.d/features/orchestration-canvas-fase2-quickwins.md
Normal file
@@ -0,0 +1,11 @@
|
||||
- **feat(dashboard):** Orchestration canvas quick wins — search box plus state/source/provider
|
||||
filter chips with a one-click clear, and per-source collapse/expand, all reflected in the URL
|
||||
so a filtered/collapsed view is shareable and survives a refresh; the detail drawer gained a
|
||||
"copy trace JSON" action and hardened error/empty-state and accessibility handling; the
|
||||
Agents-tab edges now animate traveling particles along active (running) connections; and the
|
||||
canvas node/edge status colors moved off fixed hex values onto theme-aware `--orch-status-*`
|
||||
CSS custom properties, so they adapt correctly to light/dark mode.
|
||||
- **chore(dashboard):** Orchestration UI hardening pass and the missing component/model test
|
||||
coverage it called for — `OrchestratorNode`/`ActivityNode`/`OverflowNode` rendering, the
|
||||
`?node=`/overflow-click page routing, the Agents-tab orchestrator-click no-op and
|
||||
`showCompleted` toggle, and the overview kanban's done-column sort order (#12270, #12271).
|
||||
1
changelog.d/features/orchestration-canvas.md
Normal file
1
changelog.d/features/orchestration-canvas.md
Normal file
@@ -0,0 +1 @@
|
||||
- New `/dashboard/orchestration` page: live unified view of everything running — Cloud Agent, A2A and Conductor as a real-time graph (Agents tab), the combo cascade (Routing tab, reusing the Combo Live Studio) and a state kanban (Overview tab), with a detail drawer (trace, cost, approve/cancel). Read-only over existing APIs — no new backend. Canvas concept credit: PR #11815 design
|
||||
1
changelog.d/features/rpd-rate-limit-override.md
Normal file
1
changelog.d/features/rpd-rate-limit-override.md
Normal file
@@ -0,0 +1 @@
|
||||
- **feat(providers):** add RPD (Requests Per Day) limit to provider rate limit overrides across UI, schemas, DB, and i18n ([#PR_NUMBER](https://github.com/diegosouzapw/OmniRoute/pull/PR_NUMBER))
|
||||
1
changelog.d/features/uc-direct-provider.md
Normal file
1
changelog.d/features/uc-direct-provider.md
Normal file
@@ -0,0 +1 @@
|
||||
- **feat(providers): add UC Direct (uncensored.com Developer API), the metered OpenAI-compatible surface.** A standard OpenAI-compatible passthrough (default executor) for uncensored.com's official REST API at `https://api.uncensored.com/api/v1`: `X-api-key` auth (never-expiring `uai_sk_live_` key), `POST /chat/completions` with streaming SSE and native tool-calling, and the full live metered catalog (82 models across 15 providers, discovered from the public `GET /v1/models`). Registered as provider `uc-direct` (alias `ucd`). Complements the un-metered `uc` persona provider — same models, metered credits and a plain API key instead of a subscription session.
|
||||
1
changelog.d/features/uc-persona-provider.md
Normal file
1
changelog.d/features/uc-persona-provider.md
Normal file
@@ -0,0 +1 @@
|
||||
- **feat(providers): add UC (uncensored.com), the un-metered subscription "persona" chat as an OpenAI-compatible provider.** A WebSocket web-app port: a durable Clerk credential mints a short-lived session token per connect (browserless — no API key), driving UC's persona socket. Ships the browserless email-code login (request → verify → harvest), the 19 verified persona models (Claude Opus, Gemini, Grok, GLM, Kimi, DeepSeek, MiniMax, incl. the uncensored variants), prompted `<tool>` tool-calling with a per-model code-style dialect + auto-cure retry for guardrailed models, live `<think>`/reasoning split, streaming + non-streaming OpenAI responses, and full quota/auth error surfacing (paywall / message-limit / rate-limit → 429, invalid session → 401 re-login). Full multimodal parity via the persona blob-upload layer: **vision** (image input, 15 vision-capable models), **document RAG** (PDF/doc upload, server-side extraction), **image generation** (22 models), **video generation** (14 models, async signed-url → poll), and **TTS** (streaming MP3). Registered as provider `uc` (alias `ucn`). The metered OpenAI-compatible Developer API is a separate `uc-direct` provider.
|
||||
3
changelog.d/fixes/11459-claude-code-cost-estimates.md
Normal file
3
changelog.d/fixes/11459-claude-code-cost-estimates.md
Normal file
@@ -0,0 +1,3 @@
|
||||
- Fixed the v3.8.50 Costs and Analytics dashboards so flat-rate Claude Code usage can be shown as an explicitly requested token-price estimate without changing default billed-cost semantics.
|
||||
- Fixed archived usage retention so each request is priced individually instead of pricing a day's summed tokens once, which understated archived cost whenever a day mixed cache-heavy and ordinary requests.
|
||||
- Fixed the Costs dashboard so it discloses when displayed figures include flat-rate token-price estimates instead of labelling them as billed spend, using the flag the analytics API already returns; the month-end projection and the CSV/JSON exports carry the same marker, and billed-cost mode is unchanged.
|
||||
@@ -0,0 +1,5 @@
|
||||
- Keep the embedding registry's vector width and `embedding` type on models when a synced model exists
|
||||
for the same id, so `/v1/models` no longer reports registry-described embedding models widthless or
|
||||
untyped (#11761)
|
||||
- Correct `google/gemini-embedding-001` on the OpenRouter route to 3072 dimensions, the width it
|
||||
returns when `dimensions` is not sent (#11761)
|
||||
1
changelog.d/fixes/11844-compression-oom-mitigations.md
Normal file
1
changelog.d/fixes/11844-compression-oom-mitigations.md
Normal file
@@ -0,0 +1 @@
|
||||
- **perf(compression):** OOM mitigations for large payload hashing, memoization, and token estimation ([#11844](https://github.com/diegosouzapw/OmniRoute/pull/11844) — thanks @AndrianBalanescu)
|
||||
1
changelog.d/fixes/12151-passthrough-usage-estimation.md
Normal file
1
changelog.d/fixes/12151-passthrough-usage-estimation.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(sse):** passthrough streams now estimate usage on finish when upstream closes without usage even with `stream_options.include_usage` — avoids `0 tokens / 0%` for providers that stay silent (and correctly handles trailing empty-choices usage) ([#12151](https://github.com/diegosouzapw/OmniRoute/pull/12151))
|
||||
4
changelog.d/fixes/12177-combo-clear-agent-features.md
Normal file
4
changelog.d/fixes/12177-combo-clear-agent-features.md
Normal file
@@ -0,0 +1,4 @@
|
||||
- **fix(combos):** clearing an agent feature in the combos editor now persists — unchecking
|
||||
context cache protection, or emptying the system message or tool filter, sends an explicit
|
||||
`null` instead of dropping the field from the `PUT` body, which the update merge read as
|
||||
"leave unchanged" ([#12177](https://github.com/diegosouzapw/OmniRoute/pull/12177)) — thanks @foreveryh
|
||||
5
changelog.d/fixes/12180-embedding-lazy-probe.md
Normal file
5
changelog.d/fixes/12180-embedding-lazy-probe.md
Normal file
@@ -0,0 +1,5 @@
|
||||
- **fix(memory):** self-hosted embedding endpoints now vectorize — the vector width is
|
||||
measured from the first embedding that comes back instead of being read from a registry
|
||||
that cannot describe them, so `vec_memories` is created and memories stop piling up
|
||||
unvectorized behind a green health check
|
||||
([#12180](https://github.com/diegosouzapw/OmniRoute/pull/12180)) — thanks @kanade-hoshino
|
||||
@@ -0,0 +1 @@
|
||||
- **fix(translator):** the leading `system` message now reaches Responses-API upstreams when its `content` is a content-part array — it was read as `typeof content === "string" ? content : ""`, so a prompt-caching client (Anthropic `cache_control`, the shape LiteLLM and the Anthropic SDK emit) had its entire system prompt replaced by an empty `instructions`. The request was still accepted with a normal `prompt_tokens` count, so the model answered with no instructions and nothing in the response said they were missing. Mid-conversation system turns already handled the array shape ([#7056](https://github.com/diegosouzapw/OmniRoute/pull/7056)); only the first one did not ([#12206](https://github.com/diegosouzapw/OmniRoute/issues/12206)). Regression guard: `tests/unit/translator-openai-responses-system-content-parts.test.ts`.
|
||||
1
changelog.d/fixes/12215-free-tier-overlay-freshness.md
Normal file
1
changelog.d/fixes/12215-free-tier-overlay-freshness.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(free-tier):** `/api/free-tier/summary` no longer computes its totals from a Radar feed built before the catalog the running release ships. When the cached feed is older — or carries no build date at all — the route answers from the shipped catalog, resolved through the operator's local model state so disabled and tombstoned models stay out of the numbers ([#12215](https://github.com/diegosouzapw/OmniRoute/pull/12215)).
|
||||
1
changelog.d/fixes/12222-claude-org-oauth-dedup.md
Normal file
1
changelog.d/fixes/12222-claude-org-oauth-dedup.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(oauth):** Keep a Claude personal workspace and a Team organization as separate connections — they share the same email and `accountUUID`, so the email-only OAuth dedup let the second login overwrite the first account's tokens; `organizationUUID` now disambiguates them, the way `workspaceId` does for Codex ([#12222](https://github.com/diegosouzapw/OmniRoute/pull/12222))
|
||||
@@ -0,0 +1 @@
|
||||
- **fix(resilience):** a 402 on a single paid model of a passthrough/gateway provider (e.g. `kilo-gateway`, `ollama-cloud`) no longer terminalizes the whole connection with a never-auto-recovered `credits_exhausted` status — only the paid model is locked out, so free models on the same key keep serving. 402 variant of [#3027](https://github.com/diegosouzapw/OmniRoute/issues/3027). Single-credential providers are unaffected — a 402 there is still treated as the key being genuinely out of credit ([#5239](https://github.com/diegosouzapw/OmniRoute/issues/5239) / [#10616](https://github.com/diegosouzapw/OmniRoute/issues/10616)) ([#12242](https://github.com/diegosouzapw/OmniRoute/issues/12242)) — thanks @brick30llc-ctrl
|
||||
@@ -0,0 +1 @@
|
||||
- **fix(sse):** trust `finish_reason: "length"`/`"max_tokens"` over the reasoning-consumed-token ratio in response quality validation, so a reasoning model truncated below the old 90% threshold correctly fails and retries instead of returning empty content as a silent "success" ([#12262](https://github.com/diegosouzapw/OmniRoute/pull/12262))
|
||||
1
changelog.d/fixes/12314-scoring-weights-coverage.md
Normal file
1
changelog.d/fixes/12314-scoring-weights-coverage.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(combo):** Expose the two Auto-Combo scoring factors nobody could set — the combo validation schema and the dashboard weight sliders both declared 13 of the scorer's 15 factors, so `connectionDensity` (spreads load across a provider's connections) and `quality` were dropped on save and offered nowhere. The sliders also shipped their own default table that differed from the engine's on every non-zero factor and summed to 1.05, so the percentages shown next to them added up to 105%. Both lists now match `DEFAULT_WEIGHTS`, and a test keeps them there. Note that a combo whose stored `weights` omitted the two keys was effectively running with them at zero and the other thirteen renormalized upward; it now runs with the engine's intended distribution, so its routing does shift ([#12314](https://github.com/diegosouzapw/OmniRoute/pull/12314))
|
||||
1
changelog.d/fixes/12318-free-tiers-confidence-claim.md
Normal file
1
changelog.d/fixes/12318-free-tiers-confidence-claim.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(docs):** The free-tier reference no longer says its numbers come "confidence tagged per row" — no catalog entry carries a confidence tag and the API serves none, so every figure on that page is an estimate of the same, unstated quality. The page now states what an entry does vouch for: an independently documented hard stop (set by hand with the source in a comment, never defaulted to `true`) and a prompt-training disclosure, both with live counts the `check:docs-counts` gate keeps honest ([#12318](https://github.com/diegosouzapw/OmniRoute/pull/12318))
|
||||
1
changelog.d/fixes/12321-usage-fetcher-registration.md
Normal file
1
changelog.d/fixes/12321-usage-fetcher-registration.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(usage):** `adobe-firefly` and `firefly` have had a working usage fetcher since Adobe Firefly landed, but neither was ever added to the registration list, so the provider-plugin manifest, `genericQuotaFetcher` and the free-access quota cache all reported them as having no usage support — while `USAGE_SUPPORTED_PROVIDERS` said the opposite. Both are now declared, which also means their credit balance is fetched like any other declared provider's: `registerGenericQuotaFetchers` now registers a generic quota fetcher for them, and `resolveFreeAccessState` no longer returns early. A test holds the registration list to the dispatcher's switch in both directions, which is what the module's own docstring already asked for in prose ([#12321](https://github.com/diegosouzapw/OmniRoute/pull/12321))
|
||||
1
changelog.d/fixes/12359-preserve-zwnj-zwj.md
Normal file
1
changelog.d/fixes/12359-preserve-zwnj-zwj.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(sse):** Keep ZWNJ (U+200C) and ZWJ (U+200D) in assistant text, reasoning and tool-call arguments — Persian/Kurdish half-space (`ارائهدهنده`), Arabic/Indic shaping and emoji sequences no longer lose them; the response de-obfuscation now removes joiners only between ASCII word characters, where the request side inserts them ([#12186](https://github.com/diegosouzapw/OmniRoute/issues/12186)) — thanks @rezjalibd
|
||||
1
changelog.d/fixes/12360-circuit-breaker-resolved-5xx.md
Normal file
1
changelog.d/fixes/12360-circuit-breaker-resolved-5xx.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(resilience):** count resolved upstream 5xx results against the provider circuit breaker on the chat path — `CircuitBreaker.execute()` no longer reads a resolved `{ success: false, status: 5xx }` as a success that cancels the call-site failure, so a provider answering 503s now trips its breaker instead of staying `CLOSED` at `failureCount: 1`; single-model and combo dispatches are each accounted exactly once ([#12254](https://github.com/diegosouzapw/OmniRoute/issues/12254))
|
||||
1
changelog.d/fixes/12361-codex-quota-ping-model.md
Normal file
1
changelog.d/fixes/12361-codex-quota-ping-model.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(providers):** resolve the Codex quota auto-ping model from the live provider catalog and lifecycle registry instead of the retired `gpt-5.1-codex-mini`, and pause the ping with one actionable warning when no selectable Codex model exists rather than retrying a shut-down id every cooldown window ([#11905](https://github.com/diegosouzapw/OmniRoute/issues/11905))
|
||||
1
changelog.d/fixes/12362-image-gen-response-wrapper.md
Normal file
1
changelog.d/fixes/12362-image-gen-response-wrapper.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(api):** keep the `{created, data}` wrapper on combo-routed `/v1/images/generations` responses and default Codex image results to `b64_json` on both `/v1/images/generations` and `/v1/images/edits` so Codex CLI's built-in `image_gen` can decode them ([#12268](https://github.com/diegosouzapw/OmniRoute/issues/12268))
|
||||
@@ -0,0 +1 @@
|
||||
- **fix(sse):** Name the shadowed custom provider node when a built-in provider id/alias (e.g. `openference` → `of`) reserves the prefix of an existing OpenAI/Anthropic-compatible node, so the runtime `No active credentials for provider: <built-in>` error explains that the prefix routed to the built-in and never reached the node's healthy connections, instead of contradicting the dashboard ([#11943](https://github.com/diegosouzapw/OmniRoute/issues/11943)) — thanks @morpheus9393
|
||||
@@ -0,0 +1 @@
|
||||
- **fix(guardrails):** keep `auto`/`auto/*` virtual combos exempt from the Vision Bridge `fixedModel` credential guard so a combo target is passed through instead of silently falling back to global auto-selection ([#12237](https://github.com/diegosouzapw/OmniRoute/issues/12237))
|
||||
@@ -0,0 +1 @@
|
||||
- **fix(combo):** capability-filter exhaustion caused by `max_tokens` above every target's known output limit now reports that reason (requested `max_tokens` vs the pool's highest known ceiling) instead of the unrelated "supports structured output" message ([#12229](https://github.com/diegosouzapw/OmniRoute/issues/12229)) — thanks @DW-MediaLab
|
||||
1
changelog.d/fixes/12375-least-used-backoff-tiebreak.md
Normal file
1
changelog.d/fixes/12375-least-used-backoff-tiebreak.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(auth):** the `least-used` account strategy now prefers accounts without backoff before falling back to oldest `lastUsedAt`, the same tie-break `round-robin` already applies, so a failover no longer lands on a just-rate-limited account for a single request ([#12279](https://github.com/diegosouzapw/OmniRoute/issues/12279)) — thanks @tenshiak
|
||||
@@ -0,0 +1 @@
|
||||
- **fix(docker):** the `chatgpt-web-codex-browser` image now finds the Chrome binary under `chrome-linux64/` (Chrome for Testing layout in `playwright:v1.62.0-noble`) as well as the legacy `chrome-linux/`, so the container no longer crash-loops with `exec: --headless=new: not found` ([#12024](https://github.com/diegosouzapw/OmniRoute/issues/12024))
|
||||
@@ -0,0 +1 @@
|
||||
- **fix(providers):** declare `groq/compound` and `allam-2-7b` as non-reasoning models in the curated Groq registry so `reasoning_effort` / `output_config.effort` / `thinking` from Claude Code are stripped instead of forwarded, which Groq rejected with HTTP 400 ([#12134](https://github.com/diegosouzapw/OmniRoute/issues/12134))
|
||||
1
changelog.d/fixes/12380-opencode-ambient-proxy.md
Normal file
1
changelog.d/fixes/12380-opencode-ambient-proxy.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(executors):** `OpencodeExecutor` no longer forces a direct connection when the connection has a proxy assigned in Proxy Management but no per-account proxies: the single-account fast path used to wrap the upstream dispatch in the direct-egress sentinel, discarding the ambient proxy context the chat handler had pinned from `proxy_assignments`, so API-key `opencode`/`opencode-go` connections egressed from the host IP (and hit geoblocks) despite the assignment. The direct pin is now applied only when no ambient proxy context exists ([#11894](https://github.com/diegosouzapw/OmniRoute/issues/11894) — thanks @hizzt)
|
||||
@@ -0,0 +1 @@
|
||||
- **fix(api):** `GET /v1/models` with `MODELS_CATALOG_PREFIX_MODE=canonical` (or `?prefix=canonical`) now lists providers whose registry alias is undefined or equal to their own id (Antigravity, Antigravity CLI and other self-aliased built-ins) — their single `provider/model` id was dropped by the alias/canonical duplicate guard in the static, synced, custom and alias-backed catalog loops ([#12058](https://github.com/diegosouzapw/OmniRoute/issues/12058)) — thanks @cheynetom
|
||||
@@ -0,0 +1 @@
|
||||
- **fix(translator):** Drop replayed `thinking` blocks that carry no signature (the shape produced from cross-provider `reasoning_content`) instead of stamping the default Claude signature on them, which Anthropic rejected with `400 Invalid signature in thinking block` on the next turn served by an Anthropic rung ([#12105](https://github.com/diegosouzapw/OmniRoute/issues/12105)) — thanks @atescivitci-cmd
|
||||
1
changelog.d/fixes/12387-bun-preload-package-root.md
Normal file
1
changelog.d/fixes/12387-bun-preload-package-root.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(cli):** Resolve Bun's `--preload` polyfill path against the package root instead of `dist/`, so `omniroute` installed with `bun install -g` no longer crashes at startup with `error: preload not found …/dist/open-sse/utils/setupPolyfill.ts` ([#11980](https://github.com/diegosouzapw/OmniRoute/issues/11980)) — thanks @joglomedia
|
||||
@@ -0,0 +1 @@
|
||||
- **fix(providers):** `gemini-business` now publishes its model catalog — `/v1/models` and `/v1/providers/gemini-business/models` list the 12 enterprise Gemini ids the executor understands instead of returning an empty list (#12107)
|
||||
@@ -0,0 +1 @@
|
||||
- **fix(db):** install `busy_timeout` before the SQLite connection's first statement so a process opening the database while another one closes its WAL connection waits out the transient EXCLUSIVE lock instead of dying with `database is locked`, and recognise the drivers' real BUSY/PROTOCOL/IOERR errors as transient in the corruption probe so the same lock no longer renames the database away as corrupt; deflakes `cross-process contenders never both acquire the same connection` (#12394 — thanks @pacocartones)
|
||||
1
changelog.d/fixes/12395-heavy-admission-retry-after.md
Normal file
1
changelog.d/fixes/12395-heavy-admission-retry-after.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(chat-admission):** derive the `chat_admission_busy` 503 `Retry-After` from observed heavyweight-lease occupancy — the larger of the exhausted `OMNIROUTE_CHAT_ADMISSION_QUEUE_MS` window and the time since capacity last turned over, capped at 60 s — instead of a fixed 1 s (structural) / 2 s (byte-stage) hint that invited Codex/agent fan-out clients to re-send ~1 MiB `/v1/responses` bodies every second into a gate held for the whole SSE lifetime; an idle gate keeps the historical floors ([#12135](https://github.com/diegosouzapw/OmniRoute/issues/12135)) (#12395 — thanks @pacocartones)
|
||||
@@ -0,0 +1 @@
|
||||
- **fix(api-manager):** the API key permissions modal no longer silently drops `allowedCombos` entries its Combo picker cannot render — routing-rule names such as `rt-*`, which the backend already honours — when "All" is clicked and the key is switched back to "Restrict"; those entries now survive the toggle, are listed read-only under the combo list so the count and the list agree, and are saved back verbatim instead of persisting `[]` (deny-all) (#12397 — thanks @pacocartones)
|
||||
1
changelog.d/fixes/12403-catalog-nul-literal.md
Normal file
1
changelog.d/fixes/12403-catalog-nul-literal.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(catalog):** write the NUL separator of the catalog connection memo key, the provider serviceKind memo key, the Video Bridge promotion group key and a JSON-exactness test fixture as the `\u0000` escape instead of a raw byte — same runtime value, but the raw byte made git, GitHub and ripgrep treat those files as binary (hidden PR diffs, silently skipped searches); a guard test now keeps raw NUL bytes out of `src/`, `open-sse/` and `tests/` (#12403 — thanks @pacocartones)
|
||||
@@ -0,0 +1 @@
|
||||
- Absorb `Error [AbortError]: request_signal_aborted` and DOMException AbortError shapes in the process-level client-abort crash guard so routine client disconnects no longer kill the server (exit code 7).
|
||||
@@ -0,0 +1 @@
|
||||
- **fix(memory):** Embedding Model Quick select, Embedding Source remote dropdown, and Rerank selector now list every configured provider with embedding/rerank support instead of only chat-catalog text matches plus OpenRouter live discovery; a generic OpenAI-compatible `/embeddings` + Cohere-compatible `/rerank` runtime fallback resolves any configured chat provider's embedding/rerank endpoint, so unlisted providers no longer fail with "Unknown embedding provider"; both memory selectors gained a free-text model override
|
||||
@@ -0,0 +1 @@
|
||||
- **fix(combo):** return non-retryable HTTP 400 when all candidates for a pinned native Codex turn are unavailable due to model-scoped lockout, terminating the turn cleanly while preserving turn continuity and enabling standard Combo routing on subsequent turns
|
||||
1
changelog.d/fixes/provider-assets-provenance-final.md
Normal file
1
changelog.d/fixes/provider-assets-provenance-final.md
Normal file
@@ -0,0 +1 @@
|
||||
- Render Nimble Search with the generic provider icon and serve Opper's proven logo locally.
|
||||
@@ -0,0 +1 @@
|
||||
- **docs(free-tier):** declare the counting vs deciding regimes for "is it free?" and guard the deciding path from DB-backed catalog resolution ([#12226](https://github.com/diegosouzapw/OmniRoute/pull/12226))
|
||||
1
changelog.d/maintenance/12316-mode-packs-doc-gate.md
Normal file
1
changelog.d/maintenance/12316-mode-packs-doc-gate.md
Normal file
@@ -0,0 +1 @@
|
||||
- **docs(auto-combo):** The mode pack table in `docs/routing/AUTO-COMBO.md` now lists all six shipped packs with every weight each one sets, replacing a four-pack table whose numbers had also drifted from the source. It states plainly that no pack sets `quality`, so selecting any pack silences the observed-quality signal. Six more documents that quote the scoring factor count joined the `check:docs-counts` gate, which caught five stale claims — including one naming nine factors that do not exist — and two stale mode pack counts. The dashboard routing panel, which offered four of the six packs and labelled the default strategy "6-Factor Scoring", is now covered by a test; the two packs it was missing are `reliability-first` and `chaos-mode`, the latter labelled as the fault-injection profile it is rather than as one more routing preference ([#12316](https://github.com/diegosouzapw/OmniRoute/pull/12316))
|
||||
@@ -0,0 +1 @@
|
||||
- **docs(env):** align `.env.example`, the README Bun section, and the troubleshooting guide with the code: `OMNIROUTE_USE_TURBOPACK` also governs `npm run build` (not dev-only), `bun run build` follows that flag instead of auto-selecting Webpack, `OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT` is unset by default (no request-count cap), and the structural `503 chat_admission_busy` message matches `chatAdmissionResponses.ts` (#12404 — thanks @pacocartones)
|
||||
@@ -1,401 +1,400 @@
|
||||
{
|
||||
"open-sse/transformer/responsesTransformer.ts": {
|
||||
"TS2353": 2
|
||||
"TS2353": 1
|
||||
},
|
||||
"open-sse/utils/progressTracker.ts": {
|
||||
"TS2353": 2
|
||||
"TS2353": 1
|
||||
},
|
||||
"open-sse/utils/sseHeartbeat.ts": {
|
||||
"TS2353": 2
|
||||
"TS2353": 1
|
||||
},
|
||||
"open-sse/utils/stream.ts": {
|
||||
"TS2353": 2
|
||||
"TS2353": 1
|
||||
},
|
||||
"src/app/api/assess/route.ts": {
|
||||
"TS2339": 2
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/cache/route.ts": {
|
||||
"TS2339": 2
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/cli-tools/all-statuses/route.ts": {
|
||||
"TS2339": 2
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/cli-tools/claude-settings/route.ts": {
|
||||
"TS2339": 2
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/cli-tools/cline-settings/route.ts": {
|
||||
"TS2339": 6
|
||||
},
|
||||
"src/app/api/cli-tools/codex-settings/route.ts": {
|
||||
"TS2345": 3
|
||||
},
|
||||
"src/app/api/cli-tools/grok-build-settings/route.ts": {
|
||||
"TS2304": 2
|
||||
},
|
||||
"src/app/api/cli-tools/hermes-agent-settings/route.ts": {
|
||||
"TS2345": 2
|
||||
},
|
||||
"src/app/api/cli-tools/letta-settings/route.ts": {
|
||||
"TS2339": 2
|
||||
},
|
||||
"src/app/api/cli-tools/omp-settings/route.ts": {
|
||||
"TS2339": 10
|
||||
},
|
||||
"src/app/api/cli-tools/qwen-settings/route.ts": {
|
||||
"TS2322": 2
|
||||
},
|
||||
"src/app/api/combos/auto/route.ts": {
|
||||
"TS2322": 2
|
||||
},
|
||||
"src/app/api/combos/test/route.ts": {
|
||||
"TS2345": 2,
|
||||
"TS2339": 2
|
||||
},
|
||||
"src/app/api/compression/compare/route.ts": {
|
||||
"TS2345": 2
|
||||
},
|
||||
"src/app/api/compression/preview/route.ts": {
|
||||
"TS2345": 2
|
||||
},
|
||||
"src/app/api/context/combos/[id]/route.ts": {
|
||||
"TS2345": 2
|
||||
},
|
||||
"src/app/api/context/combos/route.ts": {
|
||||
"TS2345": 2
|
||||
},
|
||||
"src/app/api/copilot/chat/route.ts": {
|
||||
"TS2345": 2
|
||||
},
|
||||
"src/app/api/guardrails/test/route.ts": {
|
||||
"TS2554": 2
|
||||
},
|
||||
"src/app/api/internal/codex-responses-ws/route.ts": {
|
||||
"TS2740": 2,
|
||||
"TS2339": 9
|
||||
},
|
||||
"src/app/api/keys/[id]/route.ts": {
|
||||
"TS2339": 2
|
||||
},
|
||||
"src/app/api/local/redis/start/route.ts": {
|
||||
"TS2339": 2
|
||||
},
|
||||
"src/app/api/local/redis/stop/route.ts": {
|
||||
"TS2339": 2
|
||||
},
|
||||
"src/app/api/logs/[id]/route.ts": {
|
||||
"TS2322": 2
|
||||
},
|
||||
"src/app/api/model-capability-overrides/route.ts": {
|
||||
"TS2339": 2
|
||||
},
|
||||
"src/app/api/model-combo-mappings/route.ts": {
|
||||
"TS2339": 2
|
||||
},
|
||||
"src/app/api/models/alias/route.ts": {
|
||||
"TS2339": 6
|
||||
},
|
||||
"src/app/api/models/route.ts": {
|
||||
"TS2345": 4,
|
||||
"TS2538": 2
|
||||
},
|
||||
"src/app/api/monitoring/health/route.ts": {
|
||||
"TS2322": 2
|
||||
},
|
||||
"src/app/api/oauth/codex/import-token/route.ts": {
|
||||
"TS2339": 4
|
||||
},
|
||||
"src/app/api/oauth/codex/import/route.ts": {
|
||||
"TS2554": 2,
|
||||
"TS2353": 2,
|
||||
"TS2339": 4
|
||||
},
|
||||
"src/app/api/oauth/cursor/login/poll/route.ts": {
|
||||
"TS2554": 2
|
||||
},
|
||||
"src/app/api/oauth/kiro/auto-import/route.ts": {
|
||||
"TS2345": 2
|
||||
},
|
||||
"src/app/api/omniroute/route/preview/route.ts": {
|
||||
"TS2345": 2
|
||||
},
|
||||
"src/app/api/playground/presets/[id]/route.ts": {
|
||||
"TS2339": 4
|
||||
},
|
||||
"src/app/api/provider-nodes/validate/route.ts": {
|
||||
"TS2339": 3
|
||||
},
|
||||
"src/app/api/providers/[id]/login/route.ts": {
|
||||
"TS2739": 2
|
||||
},
|
||||
"src/app/api/providers/[id]/models/route.ts": {
|
||||
"TS2367": 2,
|
||||
"TS2339": 3,
|
||||
"TS2322": 3,
|
||||
"TS2554": 3,
|
||||
"TS2345": 4
|
||||
},
|
||||
"src/app/api/providers/[id]/refresh-cursor/route.ts": {
|
||||
"TS2352": 2
|
||||
},
|
||||
"src/app/api/providers/[id]/refresh/route.ts": {
|
||||
"TS2345": 2,
|
||||
"TS2698": 2,
|
||||
"TS2339": 8
|
||||
},
|
||||
"src/app/api/providers/[id]/sync-models/route.ts": {
|
||||
"TS2345": 2
|
||||
},
|
||||
"src/app/api/providers/[id]/test/route.ts": {
|
||||
"TS2362": 2,
|
||||
"TS2698": 2
|
||||
},
|
||||
"src/app/api/providers/free-onboarding/route.ts": {
|
||||
"TS2345": 2
|
||||
},
|
||||
"src/app/api/providers/health-autopilot/actions/route.ts": {
|
||||
"TS2339": 2
|
||||
},
|
||||
"src/app/api/providers/route.ts": {
|
||||
"TS2352": 2,
|
||||
"TS2322": 3,
|
||||
"TS2345": 4
|
||||
},
|
||||
"src/app/api/providers/test-batch/route.ts": {
|
||||
"TS2345": 5
|
||||
},
|
||||
"src/app/api/providers/validate/route.ts": {
|
||||
"TS2322": 2
|
||||
},
|
||||
"src/app/api/providers/volcengine-plan/connect/[sessionId]/cancel/route.ts": {
|
||||
"TS2739": 2
|
||||
},
|
||||
"src/app/api/providers/volcengine-plan/connect/[sessionId]/code/route.ts": {
|
||||
"TS2739": 2
|
||||
},
|
||||
"src/app/api/providers/volcengine-plan/connect/[sessionId]/identity/route.ts": {
|
||||
"TS2739": 2
|
||||
},
|
||||
"src/app/api/providers/volcengine-plan/connect/[sessionId]/resend/route.ts": {
|
||||
"TS2739": 2
|
||||
},
|
||||
"src/app/api/providers/volcengine-plan/connect/[sessionId]/status/route.ts": {
|
||||
"TS2739": 2
|
||||
},
|
||||
"src/app/api/providers/volcengine-plan/connect/route.ts": {
|
||||
"TS2739": 2
|
||||
},
|
||||
"src/app/api/radar/local-model-state/route.ts": {
|
||||
"TS2339": 5
|
||||
},
|
||||
"src/app/api/resilience/model-cooldowns/route.ts": {
|
||||
"TS2339": 2
|
||||
},
|
||||
"src/app/api/services/_shared/installRoute.ts": {
|
||||
"TS2339": 2
|
||||
},
|
||||
"src/app/api/settings/cache-config/route.ts": {
|
||||
"TS2339": 2,
|
||||
"TS2322": 2
|
||||
},
|
||||
"src/app/api/settings/database/route.ts": {
|
||||
"src/app/api/cli-tools/codex-settings/route.ts": {
|
||||
"TS2345": 2
|
||||
},
|
||||
"src/app/api/settings/models-dev/route.ts": {
|
||||
"TS2339": 2
|
||||
"src/app/api/cli-tools/grok-build-settings/route.ts": {
|
||||
"TS2304": 1
|
||||
},
|
||||
"src/app/api/settings/obsidian/webdav/route.ts": {
|
||||
"TS2339": 2
|
||||
"src/app/api/cli-tools/hermes-agent-settings/route.ts": {
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/app/api/settings/proxies/bulk-import/route.ts": {
|
||||
"TS2345": 2
|
||||
"src/app/api/cli-tools/letta-settings/route.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/settings/proxy/cloudflare-deploy/route.ts": {
|
||||
"TS2769": 2,
|
||||
"TS2322": 3
|
||||
"src/app/api/cli-tools/omp-settings/route.ts": {
|
||||
"TS2339": 8
|
||||
},
|
||||
"src/app/api/settings/proxy/deno-deploy/route.ts": {
|
||||
"TS2322": 5
|
||||
"src/app/api/cli-tools/qwen-settings/route.ts": {
|
||||
"TS2322": 1
|
||||
},
|
||||
"src/app/api/settings/proxy/vercel-deploy/route.ts": {
|
||||
"TS2322": 4
|
||||
"src/app/api/combos/auto/route.ts": {
|
||||
"TS2322": 1
|
||||
},
|
||||
"src/app/api/settings/reasoning-routing-rules/[id]/route.ts": {
|
||||
"TS2339": 2
|
||||
"src/app/api/combos/test/route.ts": {
|
||||
"TS2345": 1,
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/settings/reasoning-routing-rules/route.ts": {
|
||||
"TS2339": 2
|
||||
"src/app/api/compression/compare/route.ts": {
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/app/api/settings/reasoning-routing-rules/simulate/route.ts": {
|
||||
"TS2322": 2,
|
||||
"TS2339": 2
|
||||
"src/app/api/compression/preview/route.ts": {
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/app/api/system/env/repair/route.ts": {
|
||||
"TS2578": 2,
|
||||
"TS2353": 4
|
||||
"src/app/api/context/combos/[id]/route.ts": {
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/app/api/system/version/route.ts": {
|
||||
"TS2769": 2
|
||||
"src/app/api/context/combos/route.ts": {
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/app/api/tools/agent-bridge/agents/[id]/detected-models/route.ts": {
|
||||
"TS2769": 2
|
||||
"src/app/api/copilot/chat/route.ts": {
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/app/api/tools/traffic-inspector/internal/ingest/route.ts": {
|
||||
"TS1117": 3,
|
||||
"TS2345": 2
|
||||
"src/app/api/guardrails/test/route.ts": {
|
||||
"TS2554": 1
|
||||
},
|
||||
"src/app/api/tools/traffic-inspector/ws/route.ts": {
|
||||
"TS2578": 2
|
||||
"src/app/api/internal/codex-responses-ws/route.ts": {
|
||||
"TS2740": 1,
|
||||
"TS2339": 7
|
||||
},
|
||||
"src/app/api/translator/send/route.ts": {
|
||||
"TS2345": 2,
|
||||
"TS2322": 2,
|
||||
"TS2339": 2
|
||||
"src/app/api/keys/[id]/route.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/translator/translate/route.ts": {
|
||||
"TS2345": 2,
|
||||
"TS2322": 2
|
||||
"src/app/api/local/redis/start/route.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/usage/analytics/route.ts": {
|
||||
"TS2352": 18
|
||||
"src/app/api/local/redis/stop/route.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/usage/combo-health-autopilot/route.ts": {
|
||||
"TS2769": 3
|
||||
"src/app/api/logs/[id]/route.ts": {
|
||||
"TS2322": 1
|
||||
},
|
||||
"src/app/api/v1/batches/route.ts": {
|
||||
"TS2339": 2
|
||||
"src/app/api/model-capability-overrides/route.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/v1/classify/route.ts": {
|
||||
"TS2322": 2
|
||||
"src/app/api/model-combo-mappings/route.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/v1/files/[id]/content/route.ts": {
|
||||
"TS2345": 2
|
||||
"src/app/api/models/alias/route.ts": {
|
||||
"TS2339": 5
|
||||
},
|
||||
"src/app/api/v1/files/route.ts": {
|
||||
"TS2339": 2
|
||||
"src/app/api/models/route.ts": {
|
||||
"TS2345": 3,
|
||||
"TS2538": 1
|
||||
},
|
||||
"src/app/api/v1/images/edits/route.ts": {
|
||||
"TS2339": 22,
|
||||
"TS2322": 5
|
||||
"src/app/api/monitoring/health/route.ts": {
|
||||
"TS2322": 1
|
||||
},
|
||||
"src/app/api/v1/messages/count_tokens/route.ts": {
|
||||
"TS2339": 3,
|
||||
"TS2322": 2
|
||||
},
|
||||
"src/app/api/v1/music/generations/route.ts": {
|
||||
"TS2322": 2,
|
||||
"TS2345": 2
|
||||
},
|
||||
"src/app/api/v1/ocr/route.ts": {
|
||||
"TS2345": 2
|
||||
},
|
||||
"src/app/api/v1/provider-plugin-manifest/route.ts": {
|
||||
"TS2345": 2
|
||||
},
|
||||
"src/app/api/v1/providers/[provider]/embeddings/route.ts": {
|
||||
"TS2339": 4,
|
||||
"TS2322": 2
|
||||
},
|
||||
"src/app/api/v1/providers/[provider]/images/generations/route.ts": {
|
||||
"TS2339": 6
|
||||
},
|
||||
"src/app/api/v1/rerank/route.ts": {
|
||||
"src/app/api/oauth/codex/import-token/route.ts": {
|
||||
"TS2339": 3
|
||||
},
|
||||
"src/app/api/v1/segment/route.ts": {
|
||||
"TS2322": 2
|
||||
"src/app/api/oauth/codex/import/route.ts": {
|
||||
"TS2554": 1,
|
||||
"TS2353": 1,
|
||||
"TS2339": 3
|
||||
},
|
||||
"src/app/api/v1/session-leases/route.ts": {
|
||||
"TS2339": 5,
|
||||
"TS2345": 2
|
||||
"src/app/api/oauth/cursor/login/poll/route.ts": {
|
||||
"TS2554": 1
|
||||
},
|
||||
"src/app/api/v1/speech-to-text/route.ts": {
|
||||
"TS2353": 2
|
||||
"src/app/api/oauth/kiro/auto-import/route.ts": {
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/app/api/v1/text-to-speech/[voiceId]/route.ts": {
|
||||
"TS2353": 2
|
||||
"src/app/api/omniroute/route/preview/route.ts": {
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/app/api/v1/web/fetch/route.ts": {
|
||||
"src/app/api/playground/presets/[id]/route.ts": {
|
||||
"TS2339": 3
|
||||
},
|
||||
"src/app/api/provider-nodes/validate/route.ts": {
|
||||
"TS2339": 2
|
||||
},
|
||||
"src/app/api/v1beta/models/route.ts": {
|
||||
"TS2345": 2,
|
||||
"TS2538": 2
|
||||
"src/app/api/providers/[id]/login/route.ts": {
|
||||
"TS2739": 1
|
||||
},
|
||||
"src/app/api/version-manager/restart/route.ts": {
|
||||
"TS2339": 2
|
||||
},
|
||||
"src/app/api/version-manager/start/route.ts": {
|
||||
"TS2339": 2
|
||||
},
|
||||
"src/app/api/version-manager/stop/route.ts": {
|
||||
"TS2339": 2
|
||||
},
|
||||
"src/app/api/webhooks/[id]/route.ts": {
|
||||
"TS2554": 2
|
||||
},
|
||||
"src/app/api/webhooks/[id]/test/route.ts": {
|
||||
"TS2352": 3
|
||||
},
|
||||
"src/app/api/webhooks/route.ts": {
|
||||
"src/app/api/providers/[id]/models/route.ts": {
|
||||
"TS2367": 1,
|
||||
"TS2339": 2,
|
||||
"TS2322": 2,
|
||||
"TS2554": 2,
|
||||
"TS2345": 2
|
||||
},
|
||||
"src/lib/db/tierConfig.ts": {
|
||||
"TS2345": 3
|
||||
},
|
||||
"src/lib/monitoring/comboHealthAutopilot.ts": {
|
||||
"TS2305": 2,
|
||||
"TS2345": 2
|
||||
"src/app/api/providers/[id]/refresh-cursor/route.ts": {
|
||||
"TS2352": 1
|
||||
},
|
||||
"src/lib/monitoring/providerHealthAutopilot.ts": {
|
||||
"TS2352": 5
|
||||
"src/app/api/providers/[id]/refresh/route.ts": {
|
||||
"TS2345": 1,
|
||||
"TS2698": 1,
|
||||
"TS2339": 6
|
||||
},
|
||||
"src/lib/omnirouteStatus.ts": {
|
||||
"src/app/api/providers/[id]/sync-models/route.ts": {
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/app/api/providers/[id]/test/route.ts": {
|
||||
"TS2362": 1,
|
||||
"TS2698": 1
|
||||
},
|
||||
"src/app/api/providers/free-onboarding/route.ts": {
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/app/api/providers/health-autopilot/actions/route.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/providers/route.ts": {
|
||||
"TS2352": 1,
|
||||
"TS2322": 2,
|
||||
"TS2558": 2
|
||||
"TS2345": 3
|
||||
},
|
||||
"src/lib/providerModels/managedModelImport.ts": {
|
||||
"TS2352": 5
|
||||
},
|
||||
"src/lib/proxySubscription/parse.ts": {
|
||||
"src/app/api/providers/test-batch/route.ts": {
|
||||
"TS2345": 4
|
||||
},
|
||||
"src/lib/quota/quotaAnalytics.ts": {
|
||||
"src/app/api/providers/validate/route.ts": {
|
||||
"TS2322": 1
|
||||
},
|
||||
"src/app/api/providers/volcengine-plan/connect/[sessionId]/cancel/route.ts": {
|
||||
"TS2739": 1
|
||||
},
|
||||
"src/app/api/providers/volcengine-plan/connect/[sessionId]/code/route.ts": {
|
||||
"TS2739": 1
|
||||
},
|
||||
"src/app/api/providers/volcengine-plan/connect/[sessionId]/identity/route.ts": {
|
||||
"TS2739": 1
|
||||
},
|
||||
"src/app/api/providers/volcengine-plan/connect/[sessionId]/resend/route.ts": {
|
||||
"TS2739": 1
|
||||
},
|
||||
"src/app/api/providers/volcengine-plan/connect/[sessionId]/status/route.ts": {
|
||||
"TS2739": 1
|
||||
},
|
||||
"src/app/api/providers/volcengine-plan/connect/route.ts": {
|
||||
"TS2739": 1
|
||||
},
|
||||
"src/app/api/radar/local-model-state/route.ts": {
|
||||
"TS2339": 4
|
||||
},
|
||||
"src/app/api/resilience/model-cooldowns/route.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/services/_shared/installRoute.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/settings/cache-config/route.ts": {
|
||||
"TS2339": 1,
|
||||
"TS2322": 1
|
||||
},
|
||||
"src/app/api/settings/database/route.ts": {
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/app/api/settings/models-dev/route.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/settings/obsidian/webdav/route.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/settings/proxies/bulk-import/route.ts": {
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/app/api/settings/proxy/cloudflare-deploy/route.ts": {
|
||||
"TS2769": 1,
|
||||
"TS2322": 2
|
||||
},
|
||||
"src/app/api/settings/proxy/deno-deploy/route.ts": {
|
||||
"TS2322": 4
|
||||
},
|
||||
"src/app/api/settings/proxy/vercel-deploy/route.ts": {
|
||||
"TS2322": 3
|
||||
},
|
||||
"src/app/api/settings/reasoning-routing-rules/[id]/route.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/settings/reasoning-routing-rules/route.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/settings/reasoning-routing-rules/simulate/route.ts": {
|
||||
"TS2322": 1,
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/system/env/repair/route.ts": {
|
||||
"TS2578": 1,
|
||||
"TS2353": 3
|
||||
},
|
||||
"src/app/api/system/version/route.ts": {
|
||||
"TS2769": 1
|
||||
},
|
||||
"src/app/api/tools/agent-bridge/agents/[id]/detected-models/route.ts": {
|
||||
"TS2769": 1
|
||||
},
|
||||
"src/app/api/tools/traffic-inspector/internal/ingest/route.ts": {
|
||||
"TS1117": 2,
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/app/api/tools/traffic-inspector/ws/route.ts": {
|
||||
"TS2578": 1
|
||||
},
|
||||
"src/app/api/translator/send/route.ts": {
|
||||
"TS2345": 1,
|
||||
"TS2322": 1,
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/translator/translate/route.ts": {
|
||||
"TS2345": 1,
|
||||
"TS2322": 1
|
||||
},
|
||||
"src/app/api/usage/analytics/route.ts": {
|
||||
"TS2352": 15
|
||||
},
|
||||
"src/app/api/usage/combo-health-autopilot/route.ts": {
|
||||
"TS2769": 2
|
||||
},
|
||||
"src/lib/quota/quotaResetTimers.ts": {
|
||||
"TS2769": 3
|
||||
"src/app/api/v1/batches/route.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/lib/usage/comboForecast.ts": {
|
||||
"TS2345": 2
|
||||
"src/app/api/v1/classify/route.ts": {
|
||||
"TS2322": 1
|
||||
},
|
||||
"src/lib/usage/comboHealth.ts": {
|
||||
"TS2345": 2
|
||||
"src/app/api/v1/files/[id]/content/route.ts": {
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/lib/usage/comboScoringInspector.ts": {
|
||||
"TS2352": 2,
|
||||
"TS2741": 2
|
||||
"src/app/api/v1/files/route.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/lib/usage/providerWindowCosts.ts": {
|
||||
"TS2322": 3,
|
||||
"TS2558": 6,
|
||||
"TS2339": 15,
|
||||
"TS2345": 2
|
||||
"src/app/api/v1/images/edits/route.ts": {
|
||||
"TS2339": 18,
|
||||
"TS2322": 4
|
||||
},
|
||||
"src/lib/vscode/modelPresentation.ts": {
|
||||
"TS2554": 2
|
||||
"src/app/api/v1/messages/count_tokens/route.ts": {
|
||||
"TS2339": 2,
|
||||
"TS2322": 1
|
||||
},
|
||||
"src/lib/ws/handshake.ts": {
|
||||
"src/app/api/v1/music/generations/route.ts": {
|
||||
"TS2322": 1,
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/app/api/v1/ocr/route.ts": {
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/app/api/v1/provider-plugin-manifest/route.ts": {
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/app/api/v1/providers/[provider]/embeddings/route.ts": {
|
||||
"TS2339": 3,
|
||||
"TS2322": 1
|
||||
},
|
||||
"src/app/api/v1/providers/[provider]/images/generations/route.ts": {
|
||||
"TS2339": 5
|
||||
},
|
||||
"src/app/api/v1/rerank/route.ts": {
|
||||
"TS2339": 2
|
||||
},
|
||||
"src/mitm/detection/index.ts": {
|
||||
"TS2741": 2
|
||||
"src/app/api/v1/segment/route.ts": {
|
||||
"TS2322": 1
|
||||
},
|
||||
"src/mitm/inspector/httpProxyServer.ts": {
|
||||
"src/app/api/v1/session-leases/route.ts": {
|
||||
"TS2339": 4,
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/app/api/v1/speech-to-text/route.ts": {
|
||||
"TS2353": 1
|
||||
},
|
||||
"src/app/api/v1/text-to-speech/[voiceId]/route.ts": {
|
||||
"TS2353": 1
|
||||
},
|
||||
"src/app/api/v1/web/fetch/route.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/v1beta/models/route.ts": {
|
||||
"TS2345": 1,
|
||||
"TS2538": 1
|
||||
},
|
||||
"src/app/api/version-manager/restart/route.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/version-manager/start/route.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/version-manager/stop/route.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/app/api/webhooks/[id]/route.ts": {
|
||||
"TS2554": 1
|
||||
},
|
||||
"src/app/api/webhooks/[id]/test/route.ts": {
|
||||
"TS2352": 2
|
||||
},
|
||||
"src/app/api/webhooks/route.ts": {
|
||||
"TS2554": 1,
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/lib/db/tierConfig.ts": {
|
||||
"TS2345": 2
|
||||
},
|
||||
"src/lib/monitoring/comboHealthAutopilot.ts": {
|
||||
"TS2305": 1,
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/lib/monitoring/providerHealthAutopilot.ts": {
|
||||
"TS2352": 4
|
||||
},
|
||||
"src/lib/omnirouteStatus.ts": {
|
||||
"TS2322": 1,
|
||||
"TS2558": 1
|
||||
},
|
||||
"src/lib/providerModels/managedModelImport.ts": {
|
||||
"TS2352": 4
|
||||
},
|
||||
"src/lib/proxySubscription/parse.ts": {
|
||||
"TS2345": 3
|
||||
},
|
||||
"src/lib/quota/quotaAnalytics.ts": {
|
||||
"TS2769": 1
|
||||
},
|
||||
"src/lib/quota/quotaResetTimers.ts": {
|
||||
"TS2769": 2
|
||||
},
|
||||
"src/shared/schemas/cliCatalog.ts": {
|
||||
"TS2554": 3
|
||||
"src/lib/usage/comboForecast.ts": {
|
||||
"TS2345": 1
|
||||
},
|
||||
"_relax_velocity_2026_08_30": "per-file TS diagnostic counts raised by 20% (289 → 455); velocity phase, see quality-baseline.json _policy."
|
||||
"src/lib/usage/comboHealth.ts": {
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/lib/usage/comboScoringInspector.ts": {
|
||||
"TS2352": 1,
|
||||
"TS2741": 1
|
||||
},
|
||||
"src/lib/usage/providerWindowCosts.ts": {
|
||||
"TS2322": 2,
|
||||
"TS2558": 5,
|
||||
"TS2339": 12,
|
||||
"TS2345": 1
|
||||
},
|
||||
"src/lib/vscode/modelPresentation.ts": {
|
||||
"TS2554": 1
|
||||
},
|
||||
"src/lib/ws/handshake.ts": {
|
||||
"TS2339": 1
|
||||
},
|
||||
"src/mitm/detection/index.ts": {
|
||||
"TS2741": 1
|
||||
},
|
||||
"src/mitm/inspector/httpProxyServer.ts": {
|
||||
"TS2769": 1
|
||||
},
|
||||
"src/shared/schemas/cliCatalog.ts": {
|
||||
"TS2554": 2
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"_justifications": {
|
||||
"@testing-library/dom": "Peer dep obrigatoria de @testing-library/react v16 (adicionada no PR #11224); Refs #9985.",
|
||||
"@testing-library/user-event": "Utilitario oficial do ecossistema testing-library para testes de UI (adicionada no PR #11224); Refs #9985.",
|
||||
"babel-plugin-react-compiler": "Official React Compiler Babel plugin (facebook/react, MIT). Required peer of Next.js 16 `reactCompiler: true`; Next declares it optional (`*`) and does not auto-install. Added by PR #11783 / issue #67.",
|
||||
"eslint-plugin-react-hooks": "React Hooks lint rules (set-state-in-effect, immutability, refs, purity) pinned at 7.0.1 by the release/v3.8.51 cycle; the 224 findings it raised are tracked in #11924. Refs #11924."
|
||||
},
|
||||
"allowed": [
|
||||
@@ -13,6 +14,7 @@
|
||||
"@dnd-kit/core",
|
||||
"@dnd-kit/sortable",
|
||||
"@dnd-kit/utilities",
|
||||
"@eslint/compat",
|
||||
"@huggingface/transformers",
|
||||
"@lobehub/icons",
|
||||
"@modelcontextprotocol/sdk",
|
||||
@@ -40,7 +42,10 @@
|
||||
"@types/ws",
|
||||
"@vitejs/plugin-react",
|
||||
"@xyflow/react",
|
||||
"ajv",
|
||||
"ajv-formats",
|
||||
"axios",
|
||||
"babel-plugin-react-compiler",
|
||||
"bcryptjs",
|
||||
"better-sqlite3",
|
||||
"bottleneck",
|
||||
@@ -63,6 +68,7 @@
|
||||
"eslint-config-next",
|
||||
"eslint-plugin-react-hooks",
|
||||
"eslint-plugin-sonarjs",
|
||||
"espree",
|
||||
"express",
|
||||
"fast-check",
|
||||
"fetch-socks",
|
||||
@@ -113,6 +119,7 @@
|
||||
"pino-abstract-transport",
|
||||
"pino-pretty",
|
||||
"playwright",
|
||||
"playwright-core",
|
||||
"playwright-ctrf-json-reporter",
|
||||
"prettier",
|
||||
"promptfoo",
|
||||
@@ -133,6 +140,7 @@
|
||||
"sqlite-vec",
|
||||
"tailwind-merge",
|
||||
"tailwindcss",
|
||||
"tiktoken",
|
||||
"tls-client-node",
|
||||
"tsup",
|
||||
"tsx",
|
||||
|
||||
@@ -297,11 +297,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"open-sse/handlers/videoGeneration/openai.ts": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"open-sse/mcp-server/__tests__/a2aLifecycle.test.ts": {
|
||||
"@typescript-eslint/no-explicit-any": {
|
||||
"count": 1
|
||||
@@ -806,69 +801,19 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"open-sse/utils/streamPayloadCollector.ts": {
|
||||
"no-restricted-syntax": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"open-sse/utils/usageTracking.ts": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"open-sse/vendor/codex-chatgpt-web/adapters/chatgpt-web/browser-worker.ts": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"open-sse/vendor/codex-chatgpt-web/adapters/chatgpt-web/environment.ts": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/HomePageClient.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 2
|
||||
},
|
||||
"react-hooks/exhaustive-deps": {
|
||||
"count": 1
|
||||
},
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"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/activity/ActivityFeedClient.tsx": {
|
||||
"react-hooks/purity": {
|
||||
"count": 1
|
||||
},
|
||||
"react-hooks/refs": {
|
||||
"count": 1
|
||||
},
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/analytics/CacheHealthTab.tsx": {
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/analytics/ComboHealthTab.tsx": {
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/analytics/CompressionAnalyticsTab.tsx": {
|
||||
@@ -876,74 +821,16 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/analytics/ProviderUtilizationTab.tsx": {
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/analytics/RouteExplainabilityTab.tsx": {
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/api-manager/ApiManagerPageClient.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/audit/A2aAuditTab.tsx": {
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/audit/ComplianceTab.tsx": {
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/audit/McpAuditTab.tsx": {
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"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/cache/components/CacheEntriesTab.tsx": {
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/cache/components/ReasoningCacheTab.tsx": {
|
||||
"react-hooks/purity": {
|
||||
"count": 1
|
||||
},
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/cache/page.tsx": {
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/cli-agents/CliAgentsPageClient.tsx": {
|
||||
"no-restricted-syntax": {
|
||||
"count": 4
|
||||
@@ -979,21 +866,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
|
||||
@@ -1014,32 +886,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": {
|
||||
@@ -1047,42 +896,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/memory/components/EditMemoryModal.tsx": {
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/memory/components/QdrantConfigCard.tsx": {
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/memory/components/tabs/MemoriesTab.tsx": {
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/memory/hooks/useEngineStatus.ts": {
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/memory/hooks/useMemorySettings.ts": {
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/onboarding/page.tsx": {
|
||||
@@ -1090,26 +906,11 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/playground/components/tabs/ApiTab.tsx": {
|
||||
"react-hooks/exhaustive-deps": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/playground/components/tabs/CompareTab.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"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
|
||||
@@ -1185,34 +986,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/radar/RadarCatalogTable.tsx": {
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/radar/intel/page.tsx": {
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/radar/page.tsx": {
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/radar/setup/page.tsx": {
|
||||
"react-hooks/preserve-manual-memoization": {
|
||||
"count": 1
|
||||
},
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"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
|
||||
@@ -1223,19 +996,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
|
||||
@@ -1281,11 +1041,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/settings/components/ModelAliasesTab.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/settings/components/ModelCapabilityOverridesTab.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
@@ -1311,41 +1066,16 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/settings/components/SessionInfoCard.tsx": {
|
||||
"react-hooks/exhaustive-deps": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/settings/components/SystemStorageTab.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/settings/components/useProxyPoolModal.ts": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/tools/agent-bridge/components/AgentList.tsx": {
|
||||
"no-restricted-syntax": {
|
||||
"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
|
||||
@@ -1356,11 +1086,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
|
||||
@@ -1376,26 +1101,11 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/usage/components/EvalsTab.tsx": {
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/usage/components/ProviderLimits/ProviderLimitCard.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 3
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/usage/components/ProviderLimits/index.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/usage/components/ProviderLimits/useCodexResetCreditRedemption.ts": {
|
||||
"react-hooks/immutability": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/usage/components/ProviderLimits/utils.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
@@ -1404,22 +1114,11 @@
|
||||
"src/app/(dashboard)/dashboard/usage/components/RateLimitStatus.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
},
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/usage/components/SessionsTab.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
},
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"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": {
|
||||
@@ -1427,27 +1126,6 @@
|
||||
"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/(dashboard)/home/ProviderQuotaWidget.tsx": {
|
||||
"react-hooks/purity": {
|
||||
"count": 1
|
||||
},
|
||||
"react-hooks/refs": {
|
||||
"count": 1
|
||||
},
|
||||
"react-hooks/set-state-in-effect": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/api/assess/route.ts": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
@@ -1706,26 +1384,11 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/docs/components/FeedbackWidget.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"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
|
||||
@@ -1754,9 +1417,6 @@
|
||||
"src/hooks/useLiveDashboard.ts": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
},
|
||||
"react-hooks/exhaustive-deps": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"src/lib/a2a/skills/healthReport.ts": {
|
||||
@@ -1829,11 +1489,6 @@
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"src/lib/credentialHealth/scheduler.ts": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/lib/db/apiKeys.ts": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 3
|
||||
@@ -2285,11 +1940,6 @@
|
||||
"count": 3
|
||||
}
|
||||
},
|
||||
"src/shared/components/PricingModal.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/shared/components/ProxyLogDetail.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
@@ -2298,9 +1948,6 @@
|
||||
"src/shared/components/RequestLoggerV2.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 3
|
||||
},
|
||||
"react-hooks/exhaustive-deps": {
|
||||
"count": 6
|
||||
}
|
||||
},
|
||||
"src/shared/components/RequestTimeline.tsx": {
|
||||
@@ -2326,26 +1973,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/shared/components/docs/CodeBlock.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/shared/components/docs/DocsBreadcrumbs.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/shared/components/docs/DocsSidebar.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/shared/components/docs/DocsThemeProvider.tsx": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 3
|
||||
}
|
||||
},
|
||||
"src/shared/constants/agentSkills.ts": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
@@ -2361,11 +1988,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
|
||||
@@ -2854,14 +2476,6 @@
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"tests/theoldllm-stress.test.ts": {
|
||||
"@typescript-eslint/no-explicit-any": {
|
||||
"count": 10
|
||||
},
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"tests/translator/testFromFile.ts": {
|
||||
"@typescript-eslint/no-explicit-any": {
|
||||
"count": 3
|
||||
@@ -3448,9 +3062,6 @@
|
||||
"tests/unit/cli-nodes-commands.test.ts": {
|
||||
"@typescript-eslint/no-explicit-any": {
|
||||
"count": 15
|
||||
},
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"tests/unit/cli-oauth-commands.test.ts": {
|
||||
@@ -3754,7 +3365,7 @@
|
||||
},
|
||||
"tests/unit/combo-routing-engine.test.ts": {
|
||||
"@typescript-eslint/no-explicit-any": {
|
||||
"count": 267
|
||||
"count": 268
|
||||
}
|
||||
},
|
||||
"tests/unit/combo-same-provider-cascade.test.ts": {
|
||||
@@ -5434,11 +5045,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"tests/unit/stream-payload-collector.test.ts": {
|
||||
"@typescript-eslint/no-explicit-any": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"tests/unit/stream-prompt-tokens-zero-upstream.test.ts": {
|
||||
"@typescript-eslint/no-unused-vars": {
|
||||
"count": 1
|
||||
@@ -5583,11 +5189,6 @@
|
||||
"count": 5
|
||||
}
|
||||
},
|
||||
"tests/unit/translator-antigravity-to-openai.test.ts": {
|
||||
"@typescript-eslint/no-explicit-any": {
|
||||
"count": 4
|
||||
}
|
||||
},
|
||||
"tests/unit/translator-claude-helper-thinking.test.ts": {
|
||||
"@typescript-eslint/no-explicit-any": {
|
||||
"count": 21
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
{
|
||||
"_rebaseline_2026_09_02_12412_grok_web_prettier": "PR #12412 (repository Prettier style applied to tests/unit/grok-web.test.ts): the reformat expands the file +277 lines (2436 -> 2713) with an identical parsed AST — no production code, no assertion changes. Cap set to 2985 rather than the exact 2713 on the operator's instruction (2026-09-02): ~10% headroom so routine additions to this suite do not re-trip the gate on formatting alone. Previous cap 2437. This is a deliberate exception to the down-only ratchet for one reformatted test file; every other entry keeps the #12411 tightening.",
|
||||
"_rebaseline_2026_09_02_v3851_merged_growth_basereds": "Base-red drain: the 2026-09-02 merge waves (#12359-#12404, #11461, #11513, #12423) each grew a frozen file at an existing chokepoint, but the rebaseline was computed in the throwaway combined validation worktree and never reached any PR branch, so the growth landed while the caps did not and check-file-size went red on the release tip. Recorded here against the merged state: src/app/api/providers/[id]/models/route.ts 2429->2432 (#12389 gemini-business listing on top of #11461's 2429); src/app/api/v1/models/catalog.ts 2066->2075 (#12381 self-aliased canonical rows + #12403 NUL escape); src/lib/db/core.ts 1740->1745 (#12394 busy_timeout ordering + probe classification); src/sse/handlers/chat.ts 2375->2384 (#12360 breaker result classification + #12365 shadowed-node error); src/sse/services/auth.ts 3420->3427 (#12375 backoffLevel tie-break); open-sse/handlers/imageGeneration.ts 3255->3259 (#11513 uc-image branch + #12423 uc-image id scoping); open-sse/utils/proxyFetch.ts 1261->1271 (#12380 hasAmbientProxyContext()); tests/unit/image-generation-handler.test.ts 2110->2133 (#12362 regression coverage); tests/unit/sse-auth.test.ts 1697->1729 (#12375 regression coverage). No cap is raised beyond the merged LOC; every other entry is untouched.",
|
||||
"_rebaseline_2026_09_02_11513_uc_provider": "PR #11513 (arminanton, feat/uc-native-standalone) own growth: open-sse/handlers/imageGeneration.ts 3243->3255 (+12) — the uc-image format branch for the UC persona provider's image surface. Additive at the existing per-format chokepoint, same rationale as _rebaseline_2026_09_02_11461_maxai_tls_profile.",
|
||||
"_rebaseline_2026_09_02_11461_maxai_tls_profile": "PR #11461 (arminanton, feat/maxai-provider) own growth, three files at existing per-provider chokepoints: open-sse/utils/proxyFetch.ts 1241->1261 (+20, the TLS_PROVIDER_PROFILE map giving MaxAI a Windows/firefox_150 impersonation profile instead of the tlsClient chrome_124/macos default); open-sse/handlers/imageGeneration.ts 3231->3243 (+12, the maxai-image format branch); src/app/api/providers/[id]/models/route.ts 2381->2429 (+48, live model listing via maxaiModels). Additive data, same no-split rationale as _rebaseline_2026_08_20_10531_freebuff_provider.",
|
||||
"_rebaseline_2026_09_02_11460_flat_rate_estimates": "PR #11460 (xiaoyaner0201, fix/11459-cc-cost-estimates) own growth: src/app/(dashboard)/dashboard/costs/CostOverviewTab.tsx 1283->1319 (+36) — the flat-rate estimate labelling and the includeFlatRateEstimates opt-in on the Costs dashboard. #11460 merged first so this ratchet re-tightening measures the real post-merge LOC; the cap still drops 2002->1319 (-683) versus the 2026-08-10 +30% loosening this PR reverses. Same own-growth rationale as _rebaseline_2026_08_20_10531_freebuff_provider.",
|
||||
"_rebaseline_2026_08_31_chatgpt_web_v4_vendor": "Pinned MIT vendor refresh from codex-chatgpt-web 0.1.16 to v4.0.6 (commit 09877fa21ffdbf20979623ef501046fc02a750d7). browser-worker.ts is preserved as the reviewed upstream browser protocol implementation; splitting the vendored file would destroy source parity and make future security/liveness updates unauditable. OmniRoute-specific DATA_DIR, Docker CDP, credential-marker, and XML decoding adaptations are covered by the ChatGPT Web Codex focused suite.",
|
||||
"_rebaseline_2026_08_20_10531_freebuff_provider": "PR #10531 (adrianaryaputra, feat/freebuff-provider-support, closes #6793) own growth: src/shared/constants/providers/apikey/gateways.ts 1283->1298 (+15, the freebuff APIKEY_PROVIDERS_GATEWAYS catalog entry, additive data at the existing registry chokepoint, same god-file no-split rationale as prior gateways.ts rebaselines) and src/app/(dashboard)/dashboard/providers/[id]/components/modals/AddApiKeyModal.tsx 1062->1067 (+5, freebuff credential placeholder/hint at the existing per-provider switch chokepoint). Covered by tests/unit/freebuff-provider.test.ts (9/9 passing).",
|
||||
"_rebaseline_2026_08_31_12212_openapi_generated": "PR #12212 (docs audit follow-up nº 3): src/app/docs/lib/openapi.generated.ts 171->1347 — the module is emitted by scripts/docs/gen-openapi-module.mjs from docs/openapi.yaml, and the spec now documents all 692 implemented routes (was 276), so the generated output grew with the spec. Frozen at the generator output size; shrink by slimming the spec, never by hand-editing the generated module. Covered by tests/unit/openapi-security-tiers.test.ts (6/6) and the check:api-docs-refs gate (692/692 paths with a real route).",
|
||||
"_rebaseline_2026_08_21_10987_logfare_provider": "PR #10987 (jonlwheat2-gif, feat/10644-logfare-provider, closes #10644) own growth: src/shared/constants/providers/apikey/gateways.ts 1298->1321 (+23, the logfare APIKEY_PROVIDERS_GATEWAYS catalog entry with Free badge/freeNote/apiHint documenting the request-logging policy, additive data at the existing registry chokepoint, same god-file no-split rationale as the prior gateways.ts rebaselines: #10531 freebuff, merge-storm 2026-08-11). Covered by tests/unit/logfare-registry.test.ts (1/1 passing).",
|
||||
"_rebaseline_2026_08_20_10574_reasoning_transport_fallback": "PR #10574 (jackjinke, fix/responses-reasoning-transport, fixes #10550) own growth: src/sse/handlers/chatHelpers.ts 1017->1019 (+2 = the new reasoningTransportFallback option threaded through executeChatWithBreaker's options destructure and its downstream handleSingleModel call, at the existing per-attempt options-passthrough chokepoint; not extractable without splitting the option-forwarding call itself). Covered by the PR's own reasoning-policy test suite (tests/unit/chatcore-translation-paths.test.ts, tests/unit/combo-attempt-body-isolation-7847.test.ts, tests/unit/reasoning-cache.test.ts, tests/unit/strip-reasoning-blobs-agentic-context-1599.test.ts among others), 446/446 focused tests passing.",
|
||||
"_rebaseline_2026_08_18_10517_zed_hosted_oauth_callback_port": "PR #10517 (phatchau036, fix/zed-hosted-oauth-callback-port) own growth: src/shared/components/OAuthModal.tsx 1131->1148 (wc -l; check-file-size.mjs counts via split(\"\\n\").length so the gate sees 1134->1149, +15/+18, crosses the frozen 1134 cap). Wires the zed-hosted native-app callback auto-complete: forceManual gating on isTrueLocalhost for zed-hosted, the loopback-redirect-URI comment block, and the exchangeToken full-URL-as-code branch, all at the existing provider-switch chokepoints this modal already carries growth for (seventh bump: 969->989->993->998->1030->1056->1100->1149; structural shrink tracked in #3501). The actual port-derivation logic lives in src/lib/oauth/providers/zed-hosted.ts (not frozen here) and was hardened during pre-merge review to use the server's own getRuntimePorts() instead of a browser-guessed scheme/port, covered by the new tests/unit/zed-hosted-loopback-port-derivation.test.ts (8/8 passing).",
|
||||
@@ -84,7 +91,7 @@
|
||||
"_rebaseline_2026_06_20_reviewprs_mine_r2_filesize": "Reconciliacao file-size pos-lote /review-prs 'apenas minhas' r2: dois frozen cresceram cumulativamente sem bump (cada PR media OK na sua base, mas o crescimento empilhou acima do frozen no tip de merge; o fast-path do release nao roda check:file-size, so release->main). (1) src/shared/constants/pricing.ts 1620->1623 (+3 = linhas de pricing Claude Code (cc) do #4440, sobre o 1620 que o #4447 ja setara para gpt-4.1-mini/nano + o3/o4-mini). (2) open-sse/executors/base.ts 1399->1407 (+8 = handling granular de reasoning_effort para Claude no Copilot do #4443). Ambos dados/wiring coesos nos chokepoints existentes; nao extraiveis. Cobertos por tests/unit (claude-code pricing / base-executor-sanitize-effort + github-claude-reasoning-effort-granular).",
|
||||
"_rebaseline_2026_06_22_4647_opencode_go_deepseek": "PR #4647 (DevEstacion/opencode-go DeepSeek V4 Pro effort variants) review feedback: open-sse/executors/base.ts 1407->1414 (+7 = supportsMaxEffortForProvider now opt-ins opencode-go+deepseek so the literal 'max' effort survives the post-transformReasoningEffortForProvider pass — without this, max was silently rewritten to xhigh (OmniRoute's internal top tier) and the opencode-go upstream rejected it. The check is scoped to opencode-go deliberately to preserve the OpenRouter-DeepSeek inverse invariant (pi#4055, asserted by base-executor-sanitize-effort test:OpenRouter DeepSeek normalizes max -> xhigh). The +5 explanatory comment is required: a naive maintainer could otherwise broaden the check to all deepseek models and break the OpenRouter contract. Cohesive at the existing supportsMaxEffortForProvider chokepoint, next to the Claude/CC-compatible check; not extractable. Covered by tests/unit/base-executor-sanitize-effort.test.ts (3 new opencode-go deepseek cases).",
|
||||
"_rebaseline_2026_06_30_v3842_release_basetsl_5480": "v3.8.42 cycle-close file-size reconciliation: open-sse/executors/base.ts 1497->1500 (+3 net = #5480 'gate claude adaptive thinking defaults' — the adaptive-thinking injection is now gated behind the operator's thinking-budget config at the existing transform chokepoint, so default/passthrough no longer force-injects). Cohesive at the existing reasoning/thinking transform site; not extractable. The fast-path release gate (PR->release/**) does not run check:file-size, so this surfaced only on the release PR (PR->main). Covered by tests/unit/base-thinking-budget-config-5312.test.ts + the #5480 gate test.",
|
||||
"_rebaseline_2026_06_20_4023_web_cookie_noauth_validation": "PR #4023 (oyi77) own growth: src/lib/providers/validation.ts 4450->4518 (+68 = a new validateWebCookieProvider that probes the provider's /models endpoint — 401/403 => AUTH_007 SESSION_EXPIRED, any other status => valid session, empty cookie => invalid, provider-not-in-registry => unsupported — plus a local STANDARD_USER_AGENT const for the probe). Cohesive validator at the validateProviderApiKey dispatch; not extractable. Covered by tests/unit/provider-validation-web-cookie-auth007.test.ts. Heavily curated on merge — the PR's branch was badly stale-based (squash-base-stale), so its tree was DESTRUCTIVE: providers/index.ts deleted live providers openadapter/dit/tokenrouter (added by #4313) and the executor/base.ts edits reverted release fixes (#4037 duckduckgo host, theoldllm gpt5 models, base.ts fetch-start-timeout). Only the purely-additive validation feature was kept (validation.ts validateWebCookieProvider + errorCodes AUTH_007 + the test). Dropped: 5 malformed new registry entries (used non-RegistryEntry fields defaultModel/auth + referenced non-existent executors -> tsc TS2353), the destructive providers/index.ts + executor reverts, the unrelated pr-*.sh automation scripts, and evals/types.ts (belongs to the deferred evals modularization #4422). Also removed the PR's fragile 'Phase 2' executor probe (ran a live upstream chat during validation + classified any 'auth'-containing error as SESSION_EXPIRED) and rewrote the test to install its fetch mock before module load (the original mocked too late and silently hit live chatgpt.com).",
|
||||
"_rebaseline_2026_06_20_4023_web_cookie_noauth_validation": "PR #4023 (oyi77) own growth: src/lib/providers/validation.ts 4450->4518 (+68 = a new validateWebCookieProvider that probes the provider's /models endpoint — 401/403 => AUTH_007 SESSION_EXPIRED, any other status => valid session, empty cookie => invalid, provider-not-in-registry => unsupported — plus a local STANDARD_USER_AGENT const for the probe). Cohesive validator at the validateProviderApiKey dispatch; not extractable. Covered by tests/unit/provider-validation-web-cookie-auth007.test.ts. Heavily curated on merge — the PR's branch was badly stale-based (squash-base-stale), so its tree was DESTRUCTIVE: providers/index.ts deleted live providers openadapter/dit/tokenrouter (added by #4313) and the executor/base.ts edits reverted release fixes (#4037 duckduckgo host, no-auth gpt5 model aliases, base.ts fetch-start-timeout). Only the purely-additive validation feature was kept (validation.ts validateWebCookieProvider + errorCodes AUTH_007 + the test). Dropped: 5 malformed new registry entries (used non-RegistryEntry fields defaultModel/auth + referenced non-existent executors -> tsc TS2353), the destructive providers/index.ts + executor reverts, the unrelated pr-*.sh automation scripts, and evals/types.ts (belongs to the deferred evals modularization #4422). Also removed the PR's fragile 'Phase 2' executor probe (ran a live upstream chat during validation + classified any 'auth'-containing error as SESSION_EXPIRED) and rewrote the test to install its fetch mock before module load (the original mocked too late and silently hit live chatgpt.com).",
|
||||
"_rebaseline_2026_06_20_1308_model_lockout_honors_reset": "port from 9router#1308 own growth: open-sse/services/accountFallback.ts 1731->1752 (+21 = the new exported pure helper selectLockoutCooldownMs + its doc comment — picks the parsed upstream reset as the model-lockout exactCooldownMs when it exceeds the base cooldown, e.g. Antigravity \"Resets in 160h\", else preserves the existing 0/base behavior) and open-sse/executors/antigravity.ts 1680->1686 (this PR +1 = parseRetryFromErrorMessage regex `reset` -> `resets?` so plural \"Resets in 160h27m24s\" matches, plus a comment line; frozen set to the SUM 1686 with the concurrent #1944 which adds +5 at the disjoint passthroughFields region of the same file, so either merge order passes — pair-file rule). The combo lockout call sites in combo.ts now pass selectLockoutCooldownMs(cooldownMs, mlSettings) instead of always base/exponential, so an exhausted model honors the real upstream reset instead of being retried within minutes. Both edits are cohesive at the existing lockout/parse chokepoints; the helper is its own pure function (not extractable further). Covered by tests/unit/combo-model-lockout-honors-reset-1308.test.ts.",
|
||||
"_rebaseline_2026_06_20_1944_antigravity_strip_output_config": "port from 9router#1944: open-sse/executors/antigravity.ts frozen set to the measured cumulative 1687 of two concurrent PRs that touch disjoint regions of this file, so either merge order passes (pair-file rule). #1944 adds +6 at the envelope passthroughFields destructuring (~line 759: drop output_config/output_format — Anthropic/Claude-Code-only fields that Google's Cloud Code envelope rejects with `400 Unknown name \"output_config\"`, which broke every Claude model on Antigravity); #1308 adds +1 at parseRetryFromErrorMessage (~line 889: regex reset->resets?). Base 1680 + 6 + 1 = 1687 (re-measured on the real merge tip — the earlier 1686 estimate was off by one). Both edits are cohesive at their chokepoints; not extractable. Covered by tests/unit/antigravity-strip-output-config-1944.test.ts.",
|
||||
"_rebaseline_2026_06_22_779_copilot_agent_antigravity_parity": "port from 9router#779 (@lukmanfauzie): open-sse/executors/antigravity.ts 1696->1721 (+25 = MAX_ANTIGRAVITY_OUTPUT_TOKENS constant + doc + final cap branch inside applyAntigravityGenerationDefaults + test-only export). Hard-caps generationConfig.maxOutputTokens at 16384 so VS Code GitHub Copilot Chat in Agent mode (which routinely requests 32K–65K tokens) stops triggering Antigravity upstream HTTP 400 'Invalid Argument'. The remaining items in upstream #779 (recursive JSON-schema sanitization, sanitizeFunctionName, $comment/enumDescriptions, functionResponse name resolution, VALIDATED mode) are already covered by OmniRoute's existing geminiHelper/geminiToolsSanitizer/openai-to-gemini pipeline — the cap is the only delta missing here. Cohesive guard at the existing generation-defaults chokepoint; not extractable. Covered by tests/unit/copilot-agent-antigravity-parity.test.ts.",
|
||||
@@ -194,43 +201,33 @@
|
||||
"_rebaseline_2026_08_24_video_bridge_fu01_fu03_fu04_result_cache_tests": "PRs #11362 (FU-01 cache hardening) + #11382 (FU-03 visual dedup policy identity) + #11383 (FU-04 focused analysis mode) own test growth: videoBridgeResultCache.test.ts <1000->1040, +40 (sum of three stacked PRs boarded together in the same merge-batch, each adding its own cache-identity assertions on the shared result-cache seam). Owner pre-authorized rebaseline for legitimate PR growth (2026-08-19 directive).",
|
||||
"_rebaseline_basered_codebuddy_cn": "Base-red fix (#4664 CodeBuddy CN): oauth-providers-config.test.ts 867->870 (+3) to align the EXPECTED provider list/config with the codebuddy-cn provider that #4664 added to the registry without updating this test (it asserts 'exactly once').",
|
||||
"_rebaseline_pr4613_compatible_provider_groups": "Reconcile #4613 already-merged growth: providers-page-utils.test.ts 1004->1052 (+48, buildCompatibleProviderGroups partition unit test). Fast-gate PR->release does not run check:file-size, so this surfaced post-merge.",
|
||||
"tests/integration/chat-pipeline.test.ts": 2493,
|
||||
"tests/integration/chatcore-compression-integration.test.ts": 1738,
|
||||
"tests/integration/skills-pipeline.test.ts": 1211,
|
||||
"tests/unit/account-fallback-service.test.ts": 2439,
|
||||
"tests/unit/adobe-firefly.test.ts": 1773,
|
||||
"tests/unit/batch_api.test.ts": 2066,
|
||||
"tests/unit/cc-compatible-provider.test.ts": 1899,
|
||||
"tests/unit/chatcore-translation-paths.test.ts": 4487,
|
||||
"tests/unit/combo-routing-engine.test.ts": 5393,
|
||||
"tests/unit/db-migration-runner.test.ts": 2339,
|
||||
"tests/unit/deepseek-web.test.ts": 1704,
|
||||
"tests/unit/executor-antigravity.test.ts": 1713,
|
||||
"tests/unit/executor-codex.test.ts": 2090,
|
||||
"tests/unit/executor-default-base.test.ts": 2370,
|
||||
"tests/unit/grok-web.test.ts": 3802,
|
||||
"tests/unit/image-generation-handler.test.ts": 3166,
|
||||
"tests/unit/model-sync-route.test.ts": 1586,
|
||||
"tests/unit/models-catalog-route.test.ts": 2553,
|
||||
"tests/unit/perplexity-web.test.ts": 2115,
|
||||
"tests/unit/provider-models-route.test.ts": 2788,
|
||||
"tests/unit/provider-validation-specialty.test.ts": 4656,
|
||||
"tests/unit/providers-page-utils.test.ts": 1726,
|
||||
"tests/unit/response-sanitizer.test.ts": 1659,
|
||||
"tests/unit/route-edge-coverage.test.ts": 1936,
|
||||
"tests/unit/search-handler-extended.test.ts": 1671,
|
||||
"tests/unit/sse-auth.test.ts": 2512,
|
||||
"tests/unit/stream-utils.test.ts": 3814,
|
||||
"tests/unit/token-refresh-service.test.ts": 2150,
|
||||
"tests/unit/translator-openai-responses-req.test.ts": 1863,
|
||||
"tests/unit/translator-openai-to-gemini.test.ts": 2531,
|
||||
"tests/unit/translator-openai-to-kiro.test.ts": 1990,
|
||||
"tests/unit/translator-resp-gemini-to-openai.test.ts": 1925,
|
||||
"tests/unit/usage-service-hardening.test.ts": 2314,
|
||||
"tests/unit/vscode-token-routes.test.ts": 1960,
|
||||
"tests/unit/guardrails/videoBridgeResultCache.test.ts": 1248,
|
||||
"tests/unit/reasoning-cache.test.ts": 1616,
|
||||
"tests/unit/chatgpt-web.test.ts": 4911
|
||||
"tests/integration/chat-pipeline.test.ts": 1644,
|
||||
"tests/unit/account-fallback-service.test.ts": 2008,
|
||||
"tests/unit/batch_api.test.ts": 1345,
|
||||
"tests/unit/cc-compatible-provider.test.ts": 1225,
|
||||
"tests/unit/chatcore-translation-paths.test.ts": 3447,
|
||||
"tests/unit/chatgpt-web.test.ts": 4911,
|
||||
"tests/unit/combo-routing-engine.test.ts": 3625,
|
||||
"tests/unit/db-migration-runner.test.ts": 1509,
|
||||
"tests/unit/executor-codex.test.ts": 1465,
|
||||
"tests/unit/executor-default-base.test.ts": 1632,
|
||||
"tests/unit/grok-web.test.ts": 2985,
|
||||
"tests/unit/image-generation-handler.test.ts": 2133,
|
||||
"tests/unit/models-catalog-route.test.ts": 1652,
|
||||
"tests/unit/perplexity-web.test.ts": 1384,
|
||||
"tests/unit/provider-models-route.test.ts": 1783,
|
||||
"tests/unit/provider-validation-specialty.test.ts": 2912,
|
||||
"tests/unit/reasoning-cache.test.ts": 1291,
|
||||
"tests/unit/route-edge-coverage.test.ts": 1244,
|
||||
"tests/unit/sse-auth.test.ts": 1729,
|
||||
"tests/unit/stream-utils.test.ts": 2517,
|
||||
"tests/unit/token-refresh-service.test.ts": 1407,
|
||||
"tests/unit/translator-openai-responses-req.test.ts": 1470,
|
||||
"tests/unit/translator-openai-to-gemini.test.ts": 1625,
|
||||
"tests/unit/translator-openai-to-kiro.test.ts": 1275,
|
||||
"tests/unit/translator-resp-gemini-to-openai.test.ts": 1234,
|
||||
"tests/unit/usage-service-hardening.test.ts": 1487,
|
||||
"tests/unit/vscode-token-routes.test.ts": 1267
|
||||
},
|
||||
"_rebaseline_2026_06_09": "Re-baseline consciente pre-release v3.8.19: 9 arquivos cresceram durante o ciclo (features mergeadas: RequestLoggerV2 +281 request-logger rework, stream +101, combo +73, chatCore +45, catalog +32 fable-5/catalog-flag, callLogs +4, accountFallback +2, usageHistory novo 840) + core.ts +7 (fix resetAllDbModuleState, PR 3536). A catraca segue valendo destes valores — proximo crescimento falha. Decisao: encolher (esp. RequestLoggerV2/chatCore) e a issue #3501 ficam para o ciclo seguinte.",
|
||||
"_rebaseline_2026_06_11_phase1f": "Phase 1f (#3501): ProviderDetailPageClient.tsx 4948→4062 (-886 LOC); 3 novos hooks extraídos. useProviderConnections.ts=954 acima do cap=800 — justificado: extração direta do god-component (zero lógica nova), própria redução do cliente supera o custo. useProviderSettings.ts=263 e useProviderModels.ts=154 já abaixo do cap.",
|
||||
@@ -365,137 +362,96 @@
|
||||
"_rebaseline_2026_07_24_responses_toolcalls_log_summary": "hartmark, fix/responses-tool-calls-log-summary own growth: open-sse/translator/response/openai-responses.ts 1163->1174 (+11). closeToolCall() now also writes the completed tool call into the shared state.toolCalls Map (already populated by the openai-to-claude / claude-to-openai / gemini-to-openai response translators) so stream.ts's completion-log summary builder (which reads state.toolCalls, not this translator's own funcCallIds/funcNames/funcArgsBuf bookkeeping) reports finish_reason \"tool_calls\" and message.tool_calls for openai->openai-responses translated streams instead of always logging \"stop\" with no tool_calls — the actual client-facing SSE events were already correct; only the persisted call-log summary was wrong. Irreducible call-site addition at the existing tool-call-close chokepoint. Covered by the new regression test in tests/unit/translator-resp-openai-responses.test.ts.",
|
||||
"_rebaseline_2026_07_25_8476_combo_input_bound_homogeneous_scope": "PR #8476 (herjarsa, fix/8375-8459-combo-image-fixes, #8375) own growth: open-sse/services/combo.ts 3642->3679 (+37 net: +29 the PR's own isInputBoundFailure short-circuit for deterministic context_length_exceeded/context_window_exceeded failures, +8 a /green-prs pre-merge fix scoping that short-circuit to homogeneous remainders only — the shipped code fired unconditionally on ANY target, regressing the intentional heterogeneous-combo fallback #6637/isContextOverflow400 protects, exactly as flagged by this PR's own review evidence but never actually implemented in the branch). The fix compares orderedTargets[i+1..] modelStr against the failing target's modelStr at the existing executeTarget dispatch chokepoint (mirrors the sameProviderNext precedent a few lines below) — irreducible call-site wiring, not extractable without hiding the dispatch boundary. Covered by tests/unit/combo-input-bound-failure-8375.test.ts (homogeneous pool still short-circuits) and the new tests/unit/combo-input-bound-heterogeneous-8375.test.ts (heterogeneous combo now correctly falls through to the larger-context target).",
|
||||
"_rebaseline_2026_07_25_adobe_firefly_reference_images": "Follow-up to #8006: storage upload + referenceBlobs for image/video and /v1/images/edits dispatch. adobeFireflyClient.ts 1958->2317 (+upload helpers, extract sources, resolve blob ids). Note: 2317 not 2316 — check-file-size.mjs counts LOC via split(\"\\n\").length (counts the trailing-newline empty element), which is 1 higher than `wc -l` on a file ending in \\n; the PR's original entry (2316) was measured with wc -l and undercounted by 1 against the actual gate.",
|
||||
"_rebaseline_pr1043_minimax_tts": "Upstream port decolua/9router#1043 (toanalien) own growth: audioSpeech.ts 965->1061 (+96). Adds MiniMax T2A v2 TTS dispatch (handleMinimaxSpeech + hexToBytes helper) — provider entry was already in audioRegistry (format: minimax-tts) but no handler existed, falling through to the OpenAI-compatible default that fails (T2A has custom shape + hex-encoded audio + base_resp envelope). New branch sits next to the other inline provider branches (xiaomi-mimo, coqui, tortoise, aws-polly) — extracting would just create indirection. Covered by tests/unit/minimax-tts-1043.test.ts (3 tests, GREEN: success, base_resp error, invalid-hex).",
|
||||
"_rebaseline_pr4592_exclude_exhausted_auto": "Reconcile #4592 already-merged growth: combo.ts 2991->3036 (+45, terminal-status quota-cutoff exclusion in buildAutoCandidates + opt-in gate). Fast-gate PR->release does not run check:file-size.",
|
||||
"open-sse/executors/antigravity.ts": 2384,
|
||||
"open-sse/executors/base.ts": 2559,
|
||||
"open-sse/executors/codex.ts": 2438,
|
||||
"open-sse/executors/cursor.ts": 2439,
|
||||
"open-sse/executors/deepseek-web.ts": 1791,
|
||||
"open-sse/executors/grok-web.ts": 1629,
|
||||
"open-sse/executors/muse-spark-web.ts": 2192,
|
||||
"open-sse/handlers/chatCore.ts": 7895,
|
||||
"open-sse/handlers/imageGeneration.ts": 4838,
|
||||
"open-sse/handlers/responseSanitizer.ts": 1760,
|
||||
"open-sse/handlers/search.ts": 2397,
|
||||
"open-sse/handlers/videoGeneration.ts": 1659,
|
||||
"open-sse/mcp-server/schemas/tools.ts": 2423,
|
||||
"open-sse/mcp-server/server.ts": 2259,
|
||||
"open-sse/mcp-server/tools/advancedTools.ts": 1748,
|
||||
"open-sse/services/accountFallback.ts": 3086,
|
||||
"open-sse/services/adobeFireflyBrowserLogin.ts": 2126,
|
||||
"open-sse/services/adobeFireflyClient.ts": 4679,
|
||||
"open-sse/services/adobeFireflySession.ts": 1565,
|
||||
"open-sse/services/claudeCodeCompatible.ts": 1876,
|
||||
"open-sse/services/combo.ts": 5691,
|
||||
"open-sse/services/compression/strategySelector.ts": 1655,
|
||||
"open-sse/services/compression/engines/ccr/index.ts": 1229,
|
||||
"_rebaseline_2026_08_22_11084_ccr_caller_gate": "PR #11084 (HouMinXi) own growth: open-sse/services/compression/engines/ccr/index.ts 1000->1024 (first listing — the engine was unlisted and drifted just over the 1000 cap; +24 are the callerSupportsCcrRetrieve gate that skips replacement entirely for callers without the retrieve tool, closing the stranded-prompt incident measured in production). Covered by tests/unit/compression/ccr-non-mcp-full-prompt-loss-7746.test.ts. Owner pre-authorized baseline bumps 2026-08-22.",
|
||||
"open-sse/services/contextManager.ts": 1202,
|
||||
"_rebaseline_2026_08_22_11113_purify_system_first": "PR #11113 (ggdayup) own growth: open-sse/services/contextManager.ts 1000->1001 (+1, purifyHistory merges the compression notice into the leading system message instead of splicing a second one mid-array — live-confirmed TokenRouter 400s; the +1 is the merge-into-leading branch, not extractable). Covered by tests/unit/context-manager-purify-system-first.test.ts. Owner pre-authorized baseline bumps 2026-08-22.",
|
||||
"open-sse/services/rateLimitManager.ts": 1821,
|
||||
"open-sse/translator/response/openai-responses.ts": 1983,
|
||||
"open-sse/utils/cursorAgentProtobuf.ts": 2348,
|
||||
"open-sse/utils/stream.ts": 4508,
|
||||
"src/app/(dashboard)/dashboard/HomePageClient.tsx": 2165,
|
||||
"src/app/(dashboard)/dashboard/analytics/ComboHealthTab.tsx": 1608,
|
||||
"src/app/(dashboard)/dashboard/api-manager/ApiManagerPageClient.tsx": 4863,
|
||||
"src/app/(dashboard)/dashboard/cache/media/MediaPageClient.tsx": 1665,
|
||||
"src/app/(dashboard)/dashboard/combos/page.tsx": 7337,
|
||||
"src/app/(dashboard)/dashboard/costs/CostOverviewTab.tsx": 2002,
|
||||
"src/app/(dashboard)/dashboard/costs/quota-share/components/PoolWizard.tsx": 1595,
|
||||
"src/app/(dashboard)/dashboard/endpoint/EndpointPageClient.tsx": 4080,
|
||||
"src/app/(dashboard)/dashboard/health/page.tsx": 1817,
|
||||
"src/app/(dashboard)/dashboard/providers/[id]/components/modals/EditConnectionModal.tsx": 2066,
|
||||
"src/app/(dashboard)/dashboard/providers/page.tsx": 3033,
|
||||
"src/app/(dashboard)/dashboard/runtime/RuntimePageClient.tsx": 1874,
|
||||
"src/app/(dashboard)/dashboard/settings/components/PricingTab.tsx": 1590,
|
||||
"src/app/(dashboard)/dashboard/settings/components/ProxyRegistryManager.tsx": 2294,
|
||||
"src/app/(dashboard)/dashboard/settings/components/ResilienceTab.tsx": 1752,
|
||||
"src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx": 2542,
|
||||
"src/app/(dashboard)/dashboard/settings/components/SystemStorageTab.tsx": 2454,
|
||||
"src/app/(dashboard)/dashboard/usage/components/BudgetTab.tsx": 1604,
|
||||
"src/app/(dashboard)/dashboard/usage/components/EvalsTab.tsx": 3351,
|
||||
"src/app/(dashboard)/dashboard/usage/components/ProviderLimits/index.tsx": 1746,
|
||||
"src/app/api/providers/[id]/models/route.ts": 3683,
|
||||
"src/app/api/v1/models/catalog.ts": 2492,
|
||||
"src/lib/db/apiKeys.ts": 2386,
|
||||
"src/lib/db/core.ts": 2558,
|
||||
"src/lib/db/migrationRunner.ts": 1718,
|
||||
"src/lib/db/models.ts": 1712,
|
||||
"src/lib/db/providers.ts": 1613,
|
||||
"src/lib/memory/retrieval.ts": 1674,
|
||||
"src/lib/tailscaleTunnel.ts": 1876,
|
||||
"src/lib/usage/providerLimits.ts": 1581,
|
||||
"src/shared/components/OAuthModal.tsx": 1769,
|
||||
"src/shared/components/RequestLoggerV2.tsx": 2542,
|
||||
"src/shared/components/analytics/charts.tsx": 1616,
|
||||
"src/shared/services/cliRuntime.ts": 1751,
|
||||
"src/sse/handlers/chat.ts": 2992,
|
||||
"src/sse/services/auth.ts": 4132,
|
||||
"_rebaseline_2026_08_28_mergebatch_v3851_provenance_sweep_batch6": "/merge-batch 2026-08-27/28 (v3.8.51) provider/asset provenance & legal compliance sweep — combining the Designer Web + Felo Web + Runtime + GPL-derived (Raycast/Hailuo Web, #11691) retirement guards at their shared chokepoints: src/sse/services/auth.ts 3432->3443 (+11, getProviderCredentials()'s two sequential retirement-check if-blocks plus getModelInfoOrRetirementResponse() catch-branch wiring), src/sse/handlers/chatHelpers.ts 1019->1037 (+18, the combined retirement-error catch branches in the executor dispatch path), src/shared/constants/providers/apikey/gateways.ts 1330->1347 (+17, catalog drift from the same PR chain since the prior 2026-08-11 rebaseline), open-sse/services/autoCombo/virtualFactory.ts 1130->1132 (+2, retirement guard import wiring at the virtual-instance factory chokepoint). Each guard call is irreducible per-mechanism wiring at pre-existing chokepoints (getExecutor, resolveExecutorWithProxy, chat.ts/chatHelpers.ts catch branches, providers.ts write paths) — combining them is additive, not a new branch. Covered by the focused test suites of each boarded PR (chatcore-executor-proxy.test.ts, provider-node-reserved-prefix.test.ts, gpl-derived-provider-removals.test.ts, migration-166-retire-gpl-derived-providers.test.ts, among others).",
|
||||
"_rebaseline_2026_08_24_lasterror_provider_error_detail": "PR (ntdat812) own growth: src/sse/services/auth.ts 3344->3346 (+2). One line is the import of describeUpstreamFailure from @/shared/utils/upstreamError, which replaces the string-only collapse `typeof errorText === \"string\" ? errorText.slice(0, 100) : \"Provider error\"` at the single markAccountUnavailable chokepoint (net 0 lines there) — the logic itself lives in upstreamError.ts, next to the extractErrorMessage it reuses, so nothing else moved into this file. The second line is the repo's own lint-staged prettier pass splitting a pre-existing two-statements-on-one-line at getProviderCredentials (`invalidateManagedLease(...); log.warn(...)`); it re-applies on any commit that touches this file, so it is not separable from the change. Covered by tests/unit/provider-error-detail-lastError.test.ts.",
|
||||
"_rebaseline_2026_08_23_11186_synced_inventory_routing": "PR #11186 (pacocartones) own growth: src/sse/services/auth.ts 3260->3337 (+77, loadAdvertisedModelsForSelfHostedConnections + the modelNotAdvertised candidate-filter predicate — pins chat routing to the connection whose synced inventory actually advertises the model, fixing spurious model-not-found on multi-host self-hosted setups; at the existing credential-selection chokepoint, not extractable without splitting the selection flow). Covered by tests/unit/chat-routing-synced-inventory-11089.test.ts. Owner pre-authorized baseline bumps 2026-08-22.",
|
||||
"tests/unit/account-fallback-service.test.ts": 2453,
|
||||
"tests/unit/provider-validation-specialty.test.ts": 4656,
|
||||
"open-sse/executors/hyperagent.ts": 1601,
|
||||
"src/lib/tokenHealthCheck.ts": 1643,
|
||||
"open-sse/executors/default.ts": 1626,
|
||||
"open-sse/executors/kiro.ts": 1668,
|
||||
"open-sse/translator/request/openai-to-kiro.ts": 1649,
|
||||
"open-sse/utils/sseHeartbeat.ts": 233,
|
||||
"open-sse/utils/proxyFetch.ts": 1493,
|
||||
"_rebaseline_2026_08_23_11177_dns_retry_classification": "PR #11177 (rqzbeh) own growth: proxyFetch.ts 1239->1244 (+5, EAI_AGAIN/ENOTFOUND/ETIMEDOUT join the retryable dispatcher classification alongside ECONNREFUSED — bounded socket retries for transient DNS failures, part of the #10443 Hermes→Antigravity stream-drop fixes). Covered by tests/unit/proxy-fetch-dns-retry-10443.test.ts. Owner pre-authorized baseline bumps 2026-08-22.",
|
||||
"_rebaseline_2026_08_11_v3850_merge_storm_provider_registry": "DRIFT do merge-storm 2026-08-11 (99 PRs mergeados no release/v3.8.50). AddApiKeyModal.tsx (PR #8949 ChatGPT Web (Codex) provider) e useProviderConnections.ts/ModelSelectModal.tsx (PRs #9011 combo test-all, #9499 image combos) = UI nova legitima acima do cap; gateways.ts = god-file de catalogo de providers que cresceu com PRs #9009/#9421/#9468/#9594 (qualquer split arriscaria corromper o merge de novo — o proprio PR #9421 quebrou o arquivo); bridge.ts (PR #8949) = ponte Chromium vendored; proxyFetch.ts 1207->1220 = drift herdado de merges. Owner autorizou rebaseline com anotacao (2026-08-11).",
|
||||
"_rebaseline_2026_08_11_v3850_merge_storm_provider_registry: DRIFT do merge-storm 2026-08-11 (99 PRs mergeados no release/v3.8.50). AddApiKeyModal.tsx (PR #8949 ChatGPT Web (Codex) provider) e useProviderConnections.ts/ModelSelectModal.tsx (PRs #9011 combo test-all, #9499 image combos) = UI nova legítima acima do cap; gateways.ts = god-file de catálogo de providers que cresceu com os PRs #9009/#9421/#9468/#9594 (qualquer split arriscaria corromper o merge de novo — o próprio PR #9421 foi o que quebrou o arquivo; sem split até o release, congelado no tamanho atual). Owner autorizou rebaseline com anotação (2026-08-11).": {
|
||||
"src/app/(dashboard)/dashboard/providers/[id]/components/modals/AddApiKeyModal.tsx": 1062,
|
||||
"src/app/(dashboard)/dashboard/providers/[id]/hooks/useProviderConnections.ts": 1051,
|
||||
"src/shared/components/ModelSelectModal.tsx": 1138,
|
||||
"src/shared/constants/providers/apikey/gateways.ts": 1250
|
||||
},
|
||||
"src/app/(dashboard)/dashboard/providers/[id]/components/modals/AddApiKeyModal.tsx": 1408,
|
||||
"_rebaseline_2026_08_23_11207_aws_polly_fields": "PR #11207 (rafacpti23, draft) own growth: AddApiKeyModal.tsx 1082->1173 (+91, AWS SigV4 credential fields for aws-polly — Access Key ID / Region / optional Session Token blocks with providerText i18n labels, at the existing per-provider form-section chokepoint; the file is the known god-modal with repeated dated rebaselines). Covered by tests/unit/dashboard/aws-polly-connection-modal-fields.test.ts. Owner pre-authorized baseline bumps 2026-08-22.",
|
||||
"_rebaseline_2026_08_22_11156_enter_check_disabled": "PR #11156 (rqzbeh) own growth: AddApiKeyModal.tsx 1080->1082 (+2, Enter keydown handler now mirrors the isCheckDisabled condition — owner-requested post-merge polish from #11056; the rest of the diff is Prettier reflow). Covered by tests/unit/ui/add-api-key-modal-enter-key.test.tsx (jsdom render test, Enter dispatch assertions).",
|
||||
"src/app/(dashboard)/dashboard/providers/[id]/hooks/useProviderConnections.ts": 1262,
|
||||
"src/shared/components/ModelSelectModal.tsx": 1366,
|
||||
"src/shared/constants/providers/apikey/gateways.ts": 1618,
|
||||
"open-sse/vendor/codex-chatgpt-web/bridge.ts": 1665,
|
||||
"_rebaseline_2026_08_11_v3850_merge_storm_provider_registry": "DRIFT do merge-storm 2026-08-11 (99 PRs mergeados no release/v3.8.50). AddApiKeyModal.tsx (PR #8949 ChatGPT Web (Codex) provider) e useProviderConnections.ts/ModelSelectModal.tsx (PRs #9011 combo test-all, #9499 image combos) = UI nova legitima acima do cap; gateways.ts = god-file de catalogo de providers que cresceu com PRs #9009/#9421/#9468/#9594 (qualquer split arriscaria corromper o merge de novo — o proprio PR #9421 quebrou o arquivo); bridge.ts (PR #8949) = ponte Chromium vendored; proxyFetch.ts 1207->1220 = drift herdado de merges. Owner autorizou rebaseline com anotacao (2026-08-11).",
|
||||
"src/lib/modelCapabilities.ts": 1287,
|
||||
"_rebaseline_2026_08_21_11034_effort_variants": "DRIFT do tip (base-red #9985): modelCapabilities.ts 1016->1072 (+56) acumulado por PRs ja mergeadas no release/v3.8.50 — principalmente #11034 (resolve effort-variant capabilities a partir do modelo base), alem de #10963/#11040/#10987 growth dos catalogos. Tip puro ficou vermelho neste gate; rebaseline no tip por push direto (owner pre-autorizou crescimento legitimo). Nao tocou no arquivo da #11038.",
|
||||
"src/app/(dashboard)/dashboard/providers/[id]/providerPageHelpers.ts": 1217,
|
||||
"open-sse/config/imageRegistry.ts": 1241,
|
||||
"src/sse/handlers/chatHelpers.ts": 1245,
|
||||
"src/shared/middleware/chatBodyAdmission.ts": 1342,
|
||||
"_rebaseline_2026_08_22_11020_sigterm_drain": "PR #11020 (RaviTharuma) own growth: chatBodyAdmission.ts 1005->1009 (+4, heavyweight admission leases now increment the SIGTERM drain counter and releaseChatAdmissionWhenDone holds it for the SSE lifetime — closes #11015; +4 are the lease/drain wiring lines at the existing admission chokepoint). Covered by tests/unit/chat-body-admission.test.ts heavyweight-lease cases. Owner pre-authorized baseline bumps 2026-08-22.",
|
||||
"_rebaseline_2026_08_20_10668_tabitoken_gateway": "#10668 (yawar-aquil) own catalog growth: src/shared/constants/providers/apikey/gateways.ts 1268->1283 (+15, entirely this PR diff -- one new tabitoken gateway entry, data lines only; base moved from 1255 to 1268 via other merges since the PR forked). Not combination drift: reproducible on the PR branch alone, so the WS5.5 release-captain rule does not apply. Extraction is not available -- the file is pure data (own header: \"Pure data; merged by apikey/index.ts via spread\") and already split into 6 family files under apikey/. Same precedent as _rebaseline_2026_08_14_imagetotext_servicekinds (#10275/#10291, gateways.ts 1250->1255, data lines only) and _rebaseline_2026_08_11_v3850_merge_storm_provider_registry (owner-authorized for this same file).",
|
||||
"_rebaseline_2026_08_20_10878_10799_provider_health_probes": "PRs #10878 (unsupported OpenAI-like validation probes stay neutral) + #10799 (preserve credential health on inconclusive NVIDIA-timeout/Antigravity-400 probes) own growth: src/app/api/providers/[id]/test/route.ts 946->1025 (+79, sum of both boarded together). Both add narrowly-scoped classification branches at the existing test-route dispatch chokepoint (unsupported-capability skip, credential-inconclusive detection) rather than new files, mirroring the prior 2026_06_27_5193 rebaseline of the same file. Covered by tests/unit/provider-validation-unsupported-neutral.test.ts + tests/unit/provider-health-inconclusive-probes.test.ts.",
|
||||
"_rebaseline_2026_08_21_10859_vision_bridge_catalog": "#10859 own growth (Vision Bridge fixes #10808/#10809): src/lib/modelCapabilities.ts 1006->1016 (+10, cmd/gpt-5.3-codex* text-only capability resolution) and open-sse/executors/commandCode.ts 988->1023 (+35, Command Code wire-model normalization for bare ids + reasoning field fallback for opencode-routed gateways). Cohesive bug fixes at the existing capability-resolution / executor chokepoints; not extractable mid-fix. Covered by tests/unit/model-capabilities-command-code-codex-textonly-10703.test.ts, tests/unit/command-code-vision.test.ts, tests/unit/opencode-mimo-reasoning-details-nonstream.test.ts. Pushed directly to release (own-session miss: the original rebaseline was made in a throwaway validation worktree and never landed on the PR branch or the release before merge).",
|
||||
"_rebaseline_2026_08_21_10907_sticky_pin_clear": "#10907 own growth: open-sse/executors/commandCode.ts 1023->1038 (+15, effort-suffix sanitization threading for the sticky-pin-clear fix). Cohesive change at the existing executor chokepoint. Covered by tests/unit/command-code-executor.test.ts.",
|
||||
"_rebaseline_2026_08_21_10986_reasoning_only_content": "#10986 own growth: open-sse/executors/commandCode.ts 1038->1059 (+21, reasoning-only content fallback — when upstream emits only reasoning-delta events and never a text-delta, surface the reasoning text as message.content in createJsonResponse and emit a synthetic content delta in createStreamResponse). Cohesive bug fix at the existing executor chokepoint (mirrors precedent style of #10907/#10859). Covered by tests/unit/command-code-executor.test.ts (2 new cases: non-stream + streaming).",
|
||||
"_rebaseline_2026_08_21_11069_m365_har_import": "#11069 own growth: AddApiKeyModal.tsx 1073->1080 (+7 = Import .har file button for the copilot-m365-web credential modal — M365 is the only provider whose credential (access_token+chathubPath) must be extracted from a DevTools HAR WebSocket URL, added as a new modal affordance). Cohesive UI at the existing modal chokepoint; not extractable. Covered by tests/unit/m365-har-import*.test.ts.",
|
||||
"_rebaseline_2026_08_23_11141_oauth_400_recovery": "PR #11141 (HouMinXi) own growth: test/route.ts 1025->1215 (+190, the reactive-400 recovery path — a fully rebuilt probe for refresh+retry on refreshable non-rotating connections, with inconclusive-status preservation and rotating-provider exclusion; all growth is the new probe builder + guards at the existing test-route dispatch, extraction would split the retry flow mid-logic). Covered by tests/unit/oauth-400-recovery.test.ts (8, bug-injection proof). Owner pre-authorized baseline bumps 2026-08-22.",
|
||||
"_rebaseline_2026_08_23_tip_drift_post_batch0823": "Tip drift after the 2026-08-23 merge wave: chatBodyAdmission.ts 1009->1118 (+109, gate count incl. +1) and auth.ts 3337->3344 (+7), both grown by merges already on origin/release/v3.8.50 (verified identical on the pristine tip) — not by the codex-appserver-hardening PR that carries this bump. Owner pre-authorized baseline bumps 2026-08-22.",
|
||||
"_rebaseline_2026_08_24_11355_cooldown_recovery_guards": "PR #11355 own growth: test/route.ts 1215->1237, +22 (startup crash-recovery guard: clearStaleCrashCooldowns() now parses the persisted rate_limited_until deadline and skips clearing rows still genuinely in the future, instead of clearing every non-terminal cooldown unconditionally). Cohesive fix at the existing test-route dispatch chokepoint alongside the #11141 probe builder. Covered by tests/unit/startup-stale-cooldown-recovery.test.ts + tests/unit/repro-zai-cooldown-cleared-by-connection-test.test.ts.",
|
||||
"_rebaseline_2026_08_24_video_bridge_fu02_fu07_sampler": "PRs #11344 (FU-02 one-frame scene-aware determinism) + #11381 (FU-07 opt-in segment_aware structural sampling) own growth: videoBridgeRuntime.ts <1000->1009, +9 (sum of both boarded together in the same merge-batch). #11344 adds the deterministic one-frame midpoint fallback + policyEffective=uniform report at the existing scene_aware seam; #11381 adds the bounded local-only FFmpeg structural pre-analysis pass (scene/freeze/blur/exposure/SI-TI) and its budget-reallocation logic. Covered by tests/unit/guardrails/videoBridgeSampler.test.ts, tests/unit/guardrails/videoBridgeFu07StructuralSampling.test.ts, tests/integration/video-bridge-sampler-ffmpeg.test.ts. Owner pre-authorized rebaseline for legitimate PR growth (2026-08-19 directive).",
|
||||
"open-sse/services/autoCombo/virtualFactory.ts": 1374,
|
||||
"_rebaseline_2026_08_29_9133_candidates_inspector_skip_flag": "#9133 own growth: open-sse/services/autoCombo/virtualFactory.ts 1138->1139 (+1, net of extraction). Fix: prepareVirtualAutoComboInputs gained an opt-in `skip` parameter so the read-only #7819 candidate inspector (open-sse/handlers/autoComboCandidates.ts) can build the FULL, unfiltered pool and decorate a resilience-blocked candidate as reachable:false instead of filterResilienceBlockedCandidates silently dropping the row before the inspector ever sees it (routing is unaffected — it never passes `skip`). The connectionsById map-building loop was extracted to buildConnectionResilienceMap() in resilienceCandidateFilter.ts (net 0 there since Prettier still breaks the call over multiple lines) and the now-unused ConnectionResilienceView import was dropped; the sole remaining growth is the new `skip` default parameter itself, which Prettier always places on its own line once the preceding options object parameter already breaks across lines — not further reducible without splitting prepareVirtualAutoComboInputs's signature away from its own body. Covered by tests/unit/auto-combo-candidates-locked-model-visible.test.ts (TDD repro: red before the fix, green after) plus the existing tests/unit/noauth-autocombo-lockout-7623.test.ts and tests/unit/auto-combo-credentialed-model-pool.test.ts (unaffected routing-path behavior).",
|
||||
"_rebaseline_2026_08_29_11481_model_exposure_list": "Feature #11481 (explicit model exposure allow/deny list for /v1/models, mirrored into auto/* combo pools) own growth on top of #9133's +1: open-sse/services/autoCombo/virtualFactory.ts 1139->1145 (measured real line count after both #9133 and #11481 merged together = one import line for filterModelExposureCandidates plus the filter-and-reassign block at the existing buildPreparedPool chokepoint, immediately after the filterPaidOnlyCandidates call it mirrors — the exact pattern #6512 already established for hidePaidModels). The actual predicate (isModelExposureAllowed, glob support via the shared globToRegex matcher) lives in the new src/shared/utils/modelExposureList.ts leaf, and the pool-filter wrapper lives in the new open-sse/services/autoCombo/modelExposureFilter.ts leaf (both well under cap) — this file only carries the minimal call-site wiring plus import, not extractable further without hiding the buildPreparedPool filter chain. Covered by tests/unit/autoCombo/model-exposure-filter-11481.test.ts (pure filter, all branches) and tests/unit/model-exposure-list.test.ts (predicate).",
|
||||
"_rebaseline_2026_08_28_mergebatch_v3851_qwen_retirement": "/merge-batch 2026-08-28 (v3.8.51): #11713 (Qwen Web retirement) own growth: open-sse/services/autoCombo/virtualFactory.ts 1132->1135 (+3, combining the Designer + Runtime retirement-guard filter into the single runtimeConnections predicate at the existing candidate-pool chokepoint, now excluding Qwen Web alongside Felo Web). Irreducible per-mechanism wiring, additive not a new branch. Covered by tests/unit/virtual-auto-combo.test.ts.",
|
||||
"_rebaseline_2026_08_28_mergebatch_v3851_chatgptweb_retirement": "/merge-batch 2026-08-28 (v3.8.51): #11754 (common ChatGPT Web retirement) own growth: open-sse/services/autoCombo/virtualFactory.ts 1135->1138 (+3, an early `available` connection filter for the retired chatgpt-web/cgpt-web ids applied to both the active and disabled-noauth connection lists, ahead of the existing Designer+Runtime runtimeConnections filter). Irreducible per-mechanism wiring, additive not a new branch. Covered by tests/unit/virtual-auto-combo.test.ts.",
|
||||
"src/lib/cloudflaredTunnel.ts": 1294,
|
||||
"src/shared/components/RequestLoggerDetail.tsx": 1334,
|
||||
"_rebaseline_2026_08_30_11703_json_tree_viewer": "/merge-batch 2026-08-30 (v3.8.51): #11703 (hartmark) own growth: src/shared/components/RequestLoggerDetail.tsx 1018->1111 (+93). The 2026-07-22 annotation on this same file said 'no further growth without split rationale' — this PR does split: the collapsible-JSON-tree rendering logic itself lives in the sibling RequestLoggerDetail.sections.tsx (PayloadSection/StreamSection extraction, +82 lines there) plus two new leaves (JsonTreeExpandControls.tsx, useTimestampTitles.ts) and a new store (jsonTreeExpandStore.ts) — all well under cap. The +93 remaining here is the irreducible call-site wiring: import + mount JsonTreeExpandControls, wire the per-section expand-level state and timestamp-tooltip hook into the existing detail panel layout. Covered by the PR's own tests/unit/dashboard/payload-section-collapsible-json.test.tsx, timestamp-titles.test.tsx, tests/unit/shared/json-tree-expand-store.test.ts, short-call-id.test.ts (43/43 vitest + 11/11 native pass).",
|
||||
"src/app/api/providers/[id]/test/route.ts": 1506,
|
||||
"src/lib/guardrails/videoBridgeRuntime.ts": 1211,
|
||||
"_rebaseline_2026_08_28_mergebatch_v3851_ratchet_bank_reconcile": "/merge-batch 2026-08-28 (v3.8.51): boarding #11702 (fix/verify-ratchet-bank object-note comparator) surfaced a large stale `frozen`/`testFrozen` snapshot on PR #11702's own branch (forked before the 08-11 banking outage — see the object-valued `_rebaseline_2026_08_11_v3850_merge_storm_provider_registry` note above, the exact bug #11702 fixes in the verifier) — its conflicting block duplicated ~85 already-tracked files with sizes smaller than the current release tip, and still listed open-sse/executors/chatgpt-web.ts (deleted by the #11754 retirement). Resolved by re-measuring every file in the union of both sides directly on the boarded tree (split(\"\\n\").length, matching check-file-size.mjs) rather than trusting either stale snapshot; dropped the dead chatgpt-web.ts entry; kept the two genuinely-new entries PR #11702's branch had that this tip did not yet track (src/app/api/providers/[id]/test/route.ts, src/lib/guardrails/videoBridgeRuntime.ts, both re-measured). Same reconciliation applied to the testFrozen block above.",
|
||||
"open-sse/executors/chatgpt-web.ts": 5056,
|
||||
"_rebaseline_2026_08_11_v3850_merge_storm_provider_registry: DRIFT do merge-storm 2026-08-11 (99 PRs mergeados no release/v3.8.50). AddApiKeyModal.tsx (PR #8949 ChatGPT Web provider) e useProviderConnections.ts/ModelSelectModal.tsx (PRs #9011 combo test-all, #9499 image combos) = UI nova legítima acima do cap; gateways.ts = god-file de catálogo de providers que cresceu com os PRs #9009/#9421/#9468/#9594 (qualquer split arriscaria corromper o merge de novo — o próprio PR #9421 foi o que quebrou o arquivo; sem split até o release, congelado no tamanho atual). Owner autorizou rebaseline com anotação (2026-08-11).": {
|
||||
"src/app/(dashboard)/dashboard/providers/[id]/components/modals/AddApiKeyModal.tsx": 1062,
|
||||
"src/app/(dashboard)/dashboard/providers/[id]/hooks/useProviderConnections.ts": 1051,
|
||||
"src/shared/components/ModelSelectModal.tsx": 1138,
|
||||
"src/shared/constants/providers/apikey/gateways.ts": 1250
|
||||
},
|
||||
"open-sse/executors/commandCode.ts": 1271
|
||||
"_rebaseline_2026_08_20_10668_tabitoken_gateway": "#10668 (yawar-aquil) own catalog growth: src/shared/constants/providers/apikey/gateways.ts 1268->1283 (+15, entirely this PR diff -- one new tabitoken gateway entry, data lines only; base moved from 1255 to 1268 via other merges since the PR forked). Not combination drift: reproducible on the PR branch alone, so the WS5.5 release-captain rule does not apply. Extraction is not available -- the file is pure data (own header: \"Pure data; merged by apikey/index.ts via spread\") and already split into 6 family files under apikey/. Same precedent as _rebaseline_2026_08_14_imagetotext_servicekinds (#10275/#10291, gateways.ts 1250->1255, data lines only) and _rebaseline_2026_08_11_v3850_merge_storm_provider_registry (owner-authorized for this same file).",
|
||||
"_rebaseline_2026_08_20_10878_10799_provider_health_probes": "PRs #10878 (unsupported OpenAI-like validation probes stay neutral) + #10799 (preserve credential health on inconclusive NVIDIA-timeout/Antigravity-400 probes) own growth: src/app/api/providers/[id]/test/route.ts 946->1025 (+79, sum of both boarded together). Both add narrowly-scoped classification branches at the existing test-route dispatch chokepoint (unsupported-capability skip, credential-inconclusive detection) rather than new files, mirroring the prior 2026_06_27_5193 rebaseline of the same file. Covered by tests/unit/provider-validation-unsupported-neutral.test.ts + tests/unit/provider-health-inconclusive-probes.test.ts.",
|
||||
"_rebaseline_2026_08_21_10859_vision_bridge_catalog": "#10859 own growth (Vision Bridge fixes #10808/#10809): src/lib/modelCapabilities.ts 1006->1016 (+10, cmd/gpt-5.3-codex* text-only capability resolution) and open-sse/executors/commandCode.ts 988->1023 (+35, Command Code wire-model normalization for bare ids + reasoning field fallback for opencode-routed gateways). Cohesive bug fixes at the existing capability-resolution / executor chokepoints; not extractable mid-fix. Covered by tests/unit/model-capabilities-command-code-codex-textonly-10703.test.ts, tests/unit/command-code-vision.test.ts, tests/unit/opencode-mimo-reasoning-details-nonstream.test.ts. Pushed directly to release (own-session miss: the original rebaseline was made in a throwaway validation worktree and never landed on the PR branch or the release before merge).",
|
||||
"_rebaseline_2026_08_21_10907_sticky_pin_clear": "#10907 own growth: open-sse/executors/commandCode.ts 1023->1038 (+15, effort-suffix sanitization threading for the sticky-pin-clear fix). Cohesive change at the existing executor chokepoint. Covered by tests/unit/command-code-executor.test.ts.",
|
||||
"_rebaseline_2026_08_21_10986_reasoning_only_content": "#10986 own growth: open-sse/executors/commandCode.ts 1038->1059 (+21, reasoning-only content fallback — when upstream emits only reasoning-delta events and never a text-delta, surface the reasoning text as message.content in createJsonResponse and emit a synthetic content delta in createStreamResponse). Cohesive bug fix at the existing executor chokepoint (mirrors precedent style of #10907/#10859). Covered by tests/unit/command-code-executor.test.ts (2 new cases: non-stream + streaming).",
|
||||
"_rebaseline_2026_08_21_11034_effort_variants": "DRIFT do tip (base-red #9985): modelCapabilities.ts 1016->1072 (+56) acumulado por PRs ja mergeadas no release/v3.8.50 — principalmente #11034 (resolve effort-variant capabilities a partir do modelo base), alem de #10963/#11040/#10987 growth dos catalogos. Tip puro ficou vermelho neste gate; rebaseline no tip por push direto (owner pre-autorizou crescimento legitimo). Nao tocou no arquivo da #11038.",
|
||||
"_rebaseline_2026_08_21_11069_m365_har_import": "#11069 own growth: AddApiKeyModal.tsx 1073->1080 (+7 = Import .har file button for the copilot-m365-web credential modal — M365 is the only provider whose credential (access_token+chathubPath) must be extracted from a DevTools HAR WebSocket URL, added as a new modal affordance). Cohesive UI at the existing modal chokepoint; not extractable. Covered by tests/unit/m365-har-import*.test.ts.",
|
||||
"_rebaseline_2026_08_22_11020_sigterm_drain": "PR #11020 (RaviTharuma) own growth: chatBodyAdmission.ts 1005->1009 (+4, heavyweight admission leases now increment the SIGTERM drain counter and releaseChatAdmissionWhenDone holds it for the SSE lifetime — closes #11015; +4 are the lease/drain wiring lines at the existing admission chokepoint). Covered by tests/unit/chat-body-admission.test.ts heavyweight-lease cases. Owner pre-authorized baseline bumps 2026-08-22.",
|
||||
"_rebaseline_2026_08_22_11084_ccr_caller_gate": "PR #11084 (HouMinXi) own growth: open-sse/services/compression/engines/ccr/index.ts 1000->1024 (first listing — the engine was unlisted and drifted just over the 1000 cap; +24 are the callerSupportsCcrRetrieve gate that skips replacement entirely for callers without the retrieve tool, closing the stranded-prompt incident measured in production). Covered by tests/unit/compression/ccr-non-mcp-full-prompt-loss-7746.test.ts. Owner pre-authorized baseline bumps 2026-08-22.",
|
||||
"_rebaseline_2026_08_22_11113_purify_system_first": "PR #11113 (ggdayup) own growth: open-sse/services/contextManager.ts 1000->1001 (+1, purifyHistory merges the compression notice into the leading system message instead of splicing a second one mid-array — live-confirmed TokenRouter 400s; the +1 is the merge-into-leading branch, not extractable). Covered by tests/unit/context-manager-purify-system-first.test.ts. Owner pre-authorized baseline bumps 2026-08-22.",
|
||||
"_rebaseline_2026_08_22_11156_enter_check_disabled": "PR #11156 (rqzbeh) own growth: AddApiKeyModal.tsx 1080->1082 (+2, Enter keydown handler now mirrors the isCheckDisabled condition — owner-requested post-merge polish from #11056; the rest of the diff is Prettier reflow). Covered by tests/unit/ui/add-api-key-modal-enter-key.test.tsx (jsdom render test, Enter dispatch assertions).",
|
||||
"_rebaseline_2026_08_23_11141_oauth_400_recovery": "PR #11141 (HouMinXi) own growth: test/route.ts 1025->1215 (+190, the reactive-400 recovery path — a fully rebuilt probe for refresh+retry on refreshable non-rotating connections, with inconclusive-status preservation and rotating-provider exclusion; all growth is the new probe builder + guards at the existing test-route dispatch, extraction would split the retry flow mid-logic). Covered by tests/unit/oauth-400-recovery.test.ts (8, bug-injection proof). Owner pre-authorized baseline bumps 2026-08-22.",
|
||||
"_rebaseline_2026_08_23_11177_dns_retry_classification": "PR #11177 (rqzbeh) own growth: proxyFetch.ts 1239->1244 (+5, EAI_AGAIN/ENOTFOUND/ETIMEDOUT join the retryable dispatcher classification alongside ECONNREFUSED — bounded socket retries for transient DNS failures, part of the #10443 Hermes→Antigravity stream-drop fixes). Covered by tests/unit/proxy-fetch-dns-retry-10443.test.ts. Owner pre-authorized baseline bumps 2026-08-22.",
|
||||
"_rebaseline_2026_08_23_11186_synced_inventory_routing": "PR #11186 (pacocartones) own growth: src/sse/services/auth.ts 3260->3337 (+77, loadAdvertisedModelsForSelfHostedConnections + the modelNotAdvertised candidate-filter predicate — pins chat routing to the connection whose synced inventory actually advertises the model, fixing spurious model-not-found on multi-host self-hosted setups; at the existing credential-selection chokepoint, not extractable without splitting the selection flow). Covered by tests/unit/chat-routing-synced-inventory-11089.test.ts. Owner pre-authorized baseline bumps 2026-08-22.",
|
||||
"_rebaseline_2026_08_23_11207_aws_polly_fields": "PR #11207 (rafacpti23, draft) own growth: AddApiKeyModal.tsx 1082->1173 (+91, AWS SigV4 credential fields for aws-polly — Access Key ID / Region / optional Session Token blocks with providerText i18n labels, at the existing per-provider form-section chokepoint; the file is the known god-modal with repeated dated rebaselines). Covered by tests/unit/dashboard/aws-polly-connection-modal-fields.test.ts. Owner pre-authorized baseline bumps 2026-08-22.",
|
||||
"_rebaseline_2026_08_23_tip_drift_post_batch0823": "Tip drift after the 2026-08-23 merge wave: chatBodyAdmission.ts 1009->1118 (+109, gate count incl. +1) and auth.ts 3337->3344 (+7), both grown by merges already on origin/release/v3.8.50 (verified identical on the pristine tip) — not by the codex-appserver-hardening PR that carries this bump. Owner pre-authorized baseline bumps 2026-08-22.",
|
||||
"_rebaseline_2026_08_24_11355_cooldown_recovery_guards": "PR #11355 own growth: test/route.ts 1215->1237, +22 (startup crash-recovery guard: clearStaleCrashCooldowns() now parses the persisted rate_limited_until deadline and skips clearing rows still genuinely in the future, instead of clearing every non-terminal cooldown unconditionally). Cohesive fix at the existing test-route dispatch chokepoint alongside the #11141 probe builder. Covered by tests/unit/startup-stale-cooldown-recovery.test.ts + tests/unit/repro-zai-cooldown-cleared-by-connection-test.test.ts.",
|
||||
"_rebaseline_2026_08_24_lasterror_provider_error_detail": "PR (ntdat812) own growth: src/sse/services/auth.ts 3344->3346 (+2). One line is the import of describeUpstreamFailure from @/shared/utils/upstreamError, which replaces the string-only collapse `typeof errorText === \"string\" ? errorText.slice(0, 100) : \"Provider error\"` at the single markAccountUnavailable chokepoint (net 0 lines there) — the logic itself lives in upstreamError.ts, next to the extractErrorMessage it reuses, so nothing else moved into this file. The second line is the repo's own lint-staged prettier pass splitting a pre-existing two-statements-on-one-line at getProviderCredentials (`invalidateManagedLease(...); log.warn(...)`); it re-applies on any commit that touches this file, so it is not separable from the change. Covered by tests/unit/provider-error-detail-lastError.test.ts.",
|
||||
"_rebaseline_2026_08_24_video_bridge_fu02_fu07_sampler": "PRs #11344 (FU-02 one-frame scene-aware determinism) + #11381 (FU-07 opt-in segment_aware structural sampling) own growth: videoBridgeRuntime.ts <1000->1009, +9 (sum of both boarded together in the same merge-batch). #11344 adds the deterministic one-frame midpoint fallback + policyEffective=uniform report at the existing scene_aware seam; #11381 adds the bounded local-only FFmpeg structural pre-analysis pass (scene/freeze/blur/exposure/SI-TI) and its budget-reallocation logic. Covered by tests/unit/guardrails/videoBridgeSampler.test.ts, tests/unit/guardrails/videoBridgeFu07StructuralSampling.test.ts, tests/integration/video-bridge-sampler-ffmpeg.test.ts. Owner pre-authorized rebaseline for legitimate PR growth (2026-08-19 directive).",
|
||||
"_rebaseline_2026_08_28_mergebatch_v3851_chatgptweb_retirement": "/merge-batch 2026-08-28 (v3.8.51): #11754 (common ChatGPT Web retirement) own growth: open-sse/services/autoCombo/virtualFactory.ts 1135->1138 (+3, an early `available` connection filter for the retired chatgpt-web/cgpt-web ids applied to both the active and disabled-noauth connection lists, ahead of the existing Designer+Runtime runtimeConnections filter). Irreducible per-mechanism wiring, additive not a new branch. Covered by tests/unit/virtual-auto-combo.test.ts.",
|
||||
"_rebaseline_2026_08_28_mergebatch_v3851_provenance_sweep_batch6": "/merge-batch 2026-08-27/28 (v3.8.51) provider/asset provenance & legal compliance sweep — combining the Designer Web + Felo Web + Runtime + GPL-derived (Raycast/Hailuo Web, #11691) retirement guards at their shared chokepoints: src/sse/services/auth.ts 3432->3443 (+11, getProviderCredentials()'s two sequential retirement-check if-blocks plus getModelInfoOrRetirementResponse() catch-branch wiring), src/sse/handlers/chatHelpers.ts 1019->1037 (+18, the combined retirement-error catch branches in the executor dispatch path), src/shared/constants/providers/apikey/gateways.ts 1330->1347 (+17, catalog drift from the same PR chain since the prior 2026-08-11 rebaseline), open-sse/services/autoCombo/virtualFactory.ts 1130->1132 (+2, retirement guard import wiring at the virtual-instance factory chokepoint). Each guard call is irreducible per-mechanism wiring at pre-existing chokepoints (getExecutor, resolveExecutorWithProxy, chat.ts/chatHelpers.ts catch branches, providers.ts write paths) — combining them is additive, not a new branch. Covered by the focused test suites of each boarded PR (chatcore-executor-proxy.test.ts, provider-node-reserved-prefix.test.ts, gpl-derived-provider-removals.test.ts, migration-166-retire-gpl-derived-providers.test.ts, among others).",
|
||||
"_rebaseline_2026_08_28_mergebatch_v3851_qwen_retirement": "/merge-batch 2026-08-28 (v3.8.51): #11713 (Qwen Web retirement) own growth: open-sse/services/autoCombo/virtualFactory.ts 1132->1135 (+3, combining the Designer + Runtime retirement-guard filter into the single runtimeConnections predicate at the existing candidate-pool chokepoint, now excluding Qwen Web alongside Felo Web). Irreducible per-mechanism wiring, additive not a new branch. Covered by tests/unit/virtual-auto-combo.test.ts.",
|
||||
"_rebaseline_2026_08_28_mergebatch_v3851_ratchet_bank_reconcile": "/merge-batch 2026-08-28 (v3.8.51): boarding #11702 (fix/verify-ratchet-bank object-note comparator) surfaced a large stale `frozen`/`testFrozen` snapshot on PR #11702's own branch (forked before the 08-11 banking outage — see the object-valued `_rebaseline_2026_08_11_v3850_merge_storm_provider_registry` note above, the exact bug #11702 fixes in the verifier) — its conflicting block duplicated ~85 already-tracked files with sizes smaller than the current release tip, and still listed open-sse/executors/chatgpt-web.ts (deleted by the #11754 retirement). Resolved by re-measuring every file in the union of both sides directly on the boarded tree (split(\"\\n\").length, matching check-file-size.mjs) rather than trusting either stale snapshot; dropped the dead chatgpt-web.ts entry; kept the two genuinely-new entries PR #11702's branch had that this tip did not yet track (src/app/api/providers/[id]/test/route.ts, src/lib/guardrails/videoBridgeRuntime.ts, both re-measured). Same reconciliation applied to the testFrozen block above.",
|
||||
"_rebaseline_2026_08_29_11481_model_exposure_list": "Feature #11481 (explicit model exposure allow/deny list for /v1/models, mirrored into auto/* combo pools) own growth on top of #9133's +1: open-sse/services/autoCombo/virtualFactory.ts 1139->1145 (measured real line count after both #9133 and #11481 merged together = one import line for filterModelExposureCandidates plus the filter-and-reassign block at the existing buildPreparedPool chokepoint, immediately after the filterPaidOnlyCandidates call it mirrors — the exact pattern #6512 already established for hidePaidModels). The actual predicate (isModelExposureAllowed, glob support via the shared globToRegex matcher) lives in the new src/shared/utils/modelExposureList.ts leaf, and the pool-filter wrapper lives in the new open-sse/services/autoCombo/modelExposureFilter.ts leaf (both well under cap) — this file only carries the minimal call-site wiring plus import, not extractable further without hiding the buildPreparedPool filter chain. Covered by tests/unit/autoCombo/model-exposure-filter-11481.test.ts (pure filter, all branches) and tests/unit/model-exposure-list.test.ts (predicate).",
|
||||
"_rebaseline_2026_08_29_9133_candidates_inspector_skip_flag": "#9133 own growth: open-sse/services/autoCombo/virtualFactory.ts 1138->1139 (+1, net of extraction). Fix: prepareVirtualAutoComboInputs gained an opt-in `skip` parameter so the read-only #7819 candidate inspector (open-sse/handlers/autoComboCandidates.ts) can build the FULL, unfiltered pool and decorate a resilience-blocked candidate as reachable:false instead of filterResilienceBlockedCandidates silently dropping the row before the inspector ever sees it (routing is unaffected — it never passes `skip`). The connectionsById map-building loop was extracted to buildConnectionResilienceMap() in resilienceCandidateFilter.ts (net 0 there since Prettier still breaks the call over multiple lines) and the now-unused ConnectionResilienceView import was dropped; the sole remaining growth is the new `skip` default parameter itself, which Prettier always places on its own line once the preceding options object parameter already breaks across lines — not further reducible without splitting prepareVirtualAutoComboInputs's signature away from its own body. Covered by tests/unit/auto-combo-candidates-locked-model-visible.test.ts (TDD repro: red before the fix, green after) plus the existing tests/unit/noauth-autocombo-lockout-7623.test.ts and tests/unit/auto-combo-credentialed-model-pool.test.ts (unaffected routing-path behavior).",
|
||||
"_rebaseline_2026_08_30_11703_json_tree_viewer": "/merge-batch 2026-08-30 (v3.8.51): #11703 (hartmark) own growth: src/shared/components/RequestLoggerDetail.tsx 1018->1111 (+93). The 2026-07-22 annotation on this same file said 'no further growth without split rationale' — this PR does split: the collapsible-JSON-tree rendering logic itself lives in the sibling RequestLoggerDetail.sections.tsx (PayloadSection/StreamSection extraction, +82 lines there) plus two new leaves (JsonTreeExpandControls.tsx, useTimestampTitles.ts) and a new store (jsonTreeExpandStore.ts) — all well under cap. The +93 remaining here is the irreducible call-site wiring: import + mount JsonTreeExpandControls, wire the per-section expand-level state and timestamp-tooltip hook into the existing detail panel layout. Covered by the PR's own tests/unit/dashboard/payload-section-collapsible-json.test.tsx, timestamp-titles.test.tsx, tests/unit/shared/json-tree-expand-store.test.ts, short-call-id.test.ts (43/43 vitest + 11/11 native pass).",
|
||||
"_rebaseline_pr1043_minimax_tts": "Upstream port decolua/9router#1043 (toanalien) own growth: audioSpeech.ts 965->1061 (+96). Adds MiniMax T2A v2 TTS dispatch (handleMinimaxSpeech + hexToBytes helper) — provider entry was already in audioRegistry (format: minimax-tts) but no handler existed, falling through to the OpenAI-compatible default that fails (T2A has custom shape + hex-encoded audio + base_resp envelope). New branch sits next to the other inline provider branches (xiaomi-mimo, coqui, tortoise, aws-polly) — extracting would just create indirection. Covered by tests/unit/minimax-tts-1043.test.ts (3 tests, GREEN: success, base_resp error, invalid-hex).",
|
||||
"_rebaseline_pr4592_exclude_exhausted_auto": "Reconcile #4592 already-merged growth: combo.ts 2991->3036 (+45, terminal-status quota-cutoff exclusion in buildAutoCandidates + opt-in gate). Fast-gate PR->release does not run check:file-size.",
|
||||
"open-sse/executors/antigravity.ts": 1665,
|
||||
"open-sse/executors/base.ts": 1751,
|
||||
"open-sse/executors/chatgpt-web.ts": 5056,
|
||||
"open-sse/executors/codex.ts": 1499,
|
||||
"open-sse/executors/cursor.ts": 1759,
|
||||
"open-sse/executors/muse-spark-web.ts": 1405,
|
||||
"open-sse/handlers/chatCore.ts": 5946,
|
||||
"open-sse/handlers/imageGeneration.ts": 3259,
|
||||
"open-sse/handlers/search.ts": 1789,
|
||||
"open-sse/mcp-server/schemas/tools.ts": 1621,
|
||||
"open-sse/mcp-server/server.ts": 1572,
|
||||
"open-sse/services/accountFallback.ts": 2422,
|
||||
"open-sse/services/adobeFireflyBrowserLogin.ts": 1401,
|
||||
"open-sse/services/combo.ts": 4023,
|
||||
"open-sse/translator/response/openai-responses.ts": 1466,
|
||||
"open-sse/utils/cursorAgentProtobuf.ts": 1547,
|
||||
"open-sse/utils/proxyFetch.ts": 1271,
|
||||
"open-sse/utils/stream.ts": 3072,
|
||||
"open-sse/vendor/codex-chatgpt-web/adapters/chatgpt-web/browser-worker.ts": 4398,
|
||||
"open-sse/vendor/codex-chatgpt-web/bridge.ts": 1322,
|
||||
"src/app/(dashboard)/dashboard/HomePageClient.tsx": 1344,
|
||||
"src/app/(dashboard)/dashboard/api-manager/ApiManagerPageClient.tsx": 3186,
|
||||
"src/app/(dashboard)/dashboard/combos/page.tsx": 5012,
|
||||
"src/app/(dashboard)/dashboard/costs/CostOverviewTab.tsx": 1319,
|
||||
"src/app/(dashboard)/dashboard/endpoint/EndpointPageClient.tsx": 2491,
|
||||
"src/app/(dashboard)/dashboard/providers/[id]/components/modals/EditConnectionModal.tsx": 1631,
|
||||
"src/app/(dashboard)/dashboard/providers/page.tsx": 2007,
|
||||
"src/app/(dashboard)/dashboard/runtime/RuntimePageClient.tsx": 1201,
|
||||
"src/app/(dashboard)/dashboard/settings/components/ProxyRegistryManager.tsx": 1475,
|
||||
"src/app/(dashboard)/dashboard/settings/components/ResilienceTab.tsx": 1271,
|
||||
"src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx": 1606,
|
||||
"src/app/(dashboard)/dashboard/settings/components/SystemStorageTab.tsx": 1597,
|
||||
"src/app/(dashboard)/dashboard/usage/components/EvalsTab.tsx": 2152,
|
||||
"src/app/api/providers/[id]/models/route.ts": 2432,
|
||||
"src/app/api/providers/[id]/test/route.ts": 1252,
|
||||
"src/app/api/v1/models/catalog.ts": 2075,
|
||||
"src/app/docs/lib/openapi.generated.ts": 1347,
|
||||
"src/lib/db/apiKeys.ts": 1610,
|
||||
"src/lib/db/core.ts": 1745,
|
||||
"src/lib/db/migrationRunner.ts": 1201,
|
||||
"src/lib/tailscaleTunnel.ts": 1208,
|
||||
"src/lib/tokenHealthCheck.ts": 1218,
|
||||
"src/shared/components/RequestLoggerV2.tsx": 1718,
|
||||
"src/shared/constants/providers/apikey/gateways.ts": 1439,
|
||||
"src/shared/services/cliRuntime.ts": 1296,
|
||||
"src/sse/handlers/chat.ts": 2384,
|
||||
"src/sse/services/auth.ts": 3427,
|
||||
"tests/unit/account-fallback-service.test.ts": 2453,
|
||||
"tests/unit/provider-validation-specialty.test.ts": 4656
|
||||
},
|
||||
"_rebaseline_base_2026_08_10_proxyfetch": "Base-red fix (green-prs sweep, issue #9985): open-sse/utils/proxyFetch.ts 1207 > cap 1000 — new proxied-TLS fetch helper introduced by the Fal reference-image work. Owner-authorized quick rebaseline to green; structural slim tracked for v3.9.0.",
|
||||
"_rebaseline_2026_07_27_v3849_train2": "Merge-train 2 (7 PRs) — owner-approved 2026-07-27. Single entry: chatCore.ts 4955->5006 (#8595, Responses multi-turn image compaction before the context hard-reject). Genuine irreducible growth at the existing compaction chokepoint in handleChatCore — the PR adds a last-resort retry against the concrete budget plus the estimateFinalInputTokens helper, both wired at the pre-existing call site rather than a new branch. Covered by tests/unit/8560-responses-image-compaction.test.ts (4 tests).",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"claude-3-7-sonnet-20250219",
|
||||
"google/gemini-2.0-flash",
|
||||
"gpt-4-0125-preview",
|
||||
"gpt-5.2-codex",
|
||||
"openai/gpt-5.2-codex"
|
||||
],
|
||||
"allowedRetiredInCatalog_note": "TODO(#11503): ratchet to burn down. Each id is retired by its vendor but still routable from the provider catalog. Removing a catalog row or adding a BUILT_IN_ALIASES forward is a maintainer call (some aggregators still serve these ids), so they are allowlisted here rather than silently dropped. Delete an entry as soon as it is forwarded or removed; never add one without a tracking issue.",
|
||||
|
||||
@@ -1,9 +1 @@
|
||||
{
|
||||
"src/lib/guardrails/videoBridgeHelpers.ts": {
|
||||
"TS2488": 2,
|
||||
"TS2365": 3,
|
||||
"TS2322": 2,
|
||||
"TS2345": 2
|
||||
},
|
||||
"_relax_velocity_2026_08_30": "per-file TS diagnostic counts raised by 20% (5 → 9); velocity phase, see quality-baseline.json _policy."
|
||||
}
|
||||
{}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{"recordType": "manifest", "schemaVersion": 1, "expectedAssetCount": 142, "auditedCommit": "7d57d9f4a15931aa33a9ab968e4e5d76a205e27c", "auditedAt": "2026-08-28", "scope": "Every regular file directly under public/providers at the audited commit.", "statusSemantics": {"proven": "Immutable source plus byte-exact or SVG path-data match.", "probable": "Repository evidence suggests provenance, but no immutable upstream match is proven.", "unresolved": "No sufficient immutable provenance evidence is recorded."}, "enforcement": "All physical files, hashes, magic MIME values, statuses, and duplicate aliases are blocking. Probable and unresolved statuses are recorded but non-blocking in schema version 1.", "legalScope": "Provenance records source matching only; it does not establish copyright or trademark clearance."}
|
||||
{"recordType": "manifest", "schemaVersion": 1, "expectedAssetCount": 141, "auditedCommit": "ccb024cfa9a7612fa65b1f1795740572369d58f5", "auditedAt": "2026-09-02", "scope": "Every regular file directly under public/providers at the audited commit.", "statusSemantics": {"proven": "Immutable source plus byte-exact or SVG path-data match.", "probable": "Repository evidence suggests provenance, but no immutable upstream match is proven.", "unresolved": "No sufficient immutable provenance evidence is recorded."}, "enforcement": "All physical files, hashes, magic MIME values, statuses, and duplicate aliases are blocking. Probable and unresolved statuses are recorded but non-blocking in schema version 1.", "legalScope": "Provenance records source matching only; it does not establish copyright or trademark clearance."}
|
||||
{"recordType": "asset", "path": "public/providers/360ai.svg", "mediaType": "image/svg+xml", "sha256": "59366fe04a4336518b8277b430f4a464a91e7ec944c9cf6f40a945c74002386d", "provenanceStatus": "proven", "source": {"kind": "npm", "url": "https://registry.npmjs.org/@lobehub/icons/-/icons-5.10.0.tgz", "ref": "5.10.0", "path": "package/es/Ai360/components/Color.js", "integrity": "sha512-CIpjkISCLRK7haDtSugGFd0o3odaJts8ewJOkUiEFtns3xvsqbl8i24eowBnjw+yMDQVQyNONlhqTD58YC6Ljg==", "packageShasum": "add1baced073a60157d39c7820b8d5c1928a1054", "match": "svg-path-data", "matchDetail": "All 5/5 local SVG path d values match the pinned Color component."}, "upstreamLicenseClaim": {"value": "MIT", "assertedBy": "@lobehub/icons@5.10.0 package/LICENSE", "evidence": "https://registry.npmjs.org/@lobehub/icons/-/icons-5.10.0.tgz#package/LICENSE", "independentlyVerified": true, "scope": "Pinned package distribution only; no trademark clearance."}, "trademarkClearance": null, "evidenceNote": "All local SVG path data matches the pinned LobeHub Color component. This proves source provenance only, not trademark clearance."}
|
||||
{"recordType": "asset", "path": "public/providers/alibaba.svg", "mediaType": "image/svg+xml", "sha256": "1cd1e7be5108d1e847508dc9e40591fb6eb29aac20bbf7f4c56c6f082359b323", "provenanceStatus": "proven", "source": {"kind": "git", "url": "https://github.com/GLINCKER/thesvg", "ref": "7870bc1c5f657d9accbb7f96cc457b8dd3363ee8", "path": "public/icons/alibaba/default.svg", "integrity": "sha256:1cd1e7be5108d1e847508dc9e40591fb6eb29aac20bbf7f4c56c6f082359b323", "match": "byte-exact"}, "upstreamLicenseClaim": {"value": "MIT", "assertedBy": "theSVG pinned registry", "evidence": "https://github.com/GLINCKER/thesvg/blob/7870bc1c5f657d9accbb7f96cc457b8dd3363ee8/src/data/icons.json", "independentlyVerified": false, "scope": "Upstream SVG copyright claim only; no trademark clearance.", "upstreamUrl": "https://alibaba.com"}, "trademarkClearance": null, "evidenceNote": "Local bytes are byte-identical to the pinned theSVG source. This proves source provenance only, not copyright or trademark clearance."}
|
||||
{"recordType": "asset", "path": "public/providers/anthropic.svg", "mediaType": "image/svg+xml", "sha256": "7fea3100bfc2a9480e181fc615d4791cab014f54674b83953785abb86dc293f0", "provenanceStatus": "proven", "source": {"kind": "git", "url": "https://github.com/GLINCKER/thesvg", "ref": "7870bc1c5f657d9accbb7f96cc457b8dd3363ee8", "path": "public/icons/anthropic/default.svg", "integrity": "sha256:7fea3100bfc2a9480e181fc615d4791cab014f54674b83953785abb86dc293f0", "match": "byte-exact"}, "upstreamLicenseClaim": {"value": "CC0-1.0", "assertedBy": "theSVG pinned registry", "evidence": "https://github.com/GLINCKER/thesvg/blob/7870bc1c5f657d9accbb7f96cc457b8dd3363ee8/src/data/icons.json", "independentlyVerified": false, "scope": "Upstream SVG copyright claim only; no trademark clearance.", "upstreamUrl": "https://www.anthropic.com/"}, "trademarkClearance": null, "evidenceNote": "Local bytes are byte-identical to the pinned theSVG source. This proves source provenance only, not copyright or trademark clearance."}
|
||||
@@ -80,7 +80,6 @@
|
||||
{"recordType": "asset", "path": "public/providers/moonshot.svg", "mediaType": "image/svg+xml", "sha256": "a6ac95d972fdb044cd4155b0f75d9c1c816348868c810f63c7e5c8840c9e3e12", "provenanceStatus": "proven", "source": {"kind": "git", "url": "https://github.com/GLINCKER/thesvg", "ref": "7870bc1c5f657d9accbb7f96cc457b8dd3363ee8", "path": "public/icons/moonshot/default.svg", "integrity": "sha256:a6ac95d972fdb044cd4155b0f75d9c1c816348868c810f63c7e5c8840c9e3e12", "match": "byte-exact"}, "upstreamLicenseClaim": {"value": "MIT", "assertedBy": "theSVG pinned registry", "evidence": "https://github.com/GLINCKER/thesvg/blob/7870bc1c5f657d9accbb7f96cc457b8dd3363ee8/src/data/icons.json", "independentlyVerified": false, "scope": "Upstream SVG copyright claim only; no trademark clearance.", "upstreamUrl": "https://moonshot.cn"}, "trademarkClearance": null, "evidenceNote": "Local bytes are byte-identical to the pinned theSVG source. This proves source provenance only, not copyright or trademark clearance."}
|
||||
{"recordType": "asset", "path": "public/providers/morph.svg", "mediaType": "image/svg+xml", "sha256": "0fdb479e13c5d5de15aa89d1f87c8d55f8f8a56d33fc5dee8c566d2e0dbd5b96", "provenanceStatus": "proven", "source": {"kind": "git", "url": "https://github.com/GLINCKER/thesvg", "ref": "7870bc1c5f657d9accbb7f96cc457b8dd3363ee8", "path": "public/icons/morph/default.svg", "integrity": "sha256:0fdb479e13c5d5de15aa89d1f87c8d55f8f8a56d33fc5dee8c566d2e0dbd5b96", "match": "byte-exact"}, "upstreamLicenseClaim": {"value": "MIT", "assertedBy": "theSVG pinned registry", "evidence": "https://github.com/GLINCKER/thesvg/blob/7870bc1c5f657d9accbb7f96cc457b8dd3363ee8/src/data/icons.json", "independentlyVerified": false, "scope": "Upstream SVG copyright claim only; no trademark clearance.", "upstreamUrl": "https://morphllm.com"}, "trademarkClearance": null, "evidenceNote": "Local bytes are byte-identical to the pinned theSVG source. This proves source provenance only, not copyright or trademark clearance."}
|
||||
{"recordType": "asset", "path": "public/providers/nebius.svg", "mediaType": "image/svg+xml", "sha256": "fb190b4efb1d143442ef6c5eb0258801fc27b7316e88216c59a0f4b58b8b0281", "provenanceStatus": "proven", "source": {"kind": "git", "url": "https://github.com/GLINCKER/thesvg", "ref": "7870bc1c5f657d9accbb7f96cc457b8dd3363ee8", "path": "public/icons/nebius/default.svg", "integrity": "sha256:fb190b4efb1d143442ef6c5eb0258801fc27b7316e88216c59a0f4b58b8b0281", "match": "byte-exact"}, "upstreamLicenseClaim": {"value": "MIT", "assertedBy": "theSVG pinned registry", "evidence": "https://github.com/GLINCKER/thesvg/blob/7870bc1c5f657d9accbb7f96cc457b8dd3363ee8/src/data/icons.json", "independentlyVerified": false, "scope": "Upstream SVG copyright claim only; no trademark clearance.", "upstreamUrl": "https://nebius.com"}, "trademarkClearance": null, "evidenceNote": "Local bytes are byte-identical to the pinned theSVG source. This proves source provenance only, not copyright or trademark clearance."}
|
||||
{"recordType": "asset", "path": "public/providers/nimble-search.svg", "mediaType": "image/svg+xml", "sha256": "c22d214880d1cbf48aa08617fbc245b96f7372fe5602ef1382978eee522c6575", "provenanceStatus": "unresolved", "source": null, "upstreamLicenseClaim": null, "trademarkClearance": null, "evidenceNote": "Added by an unrelated already-merged provider PR (#11620/#11629); no provenance research recorded yet. Flagged unresolved pending review, per schema v1 (non-blocking)."}
|
||||
{"recordType": "asset", "path": "public/providers/nomic.svg", "mediaType": "image/svg+xml", "sha256": "73cc513c9d5f460ec8f00a097f3fabaa54c0e1f824944412e9a4461c0620fba6", "provenanceStatus": "probable", "source": null, "upstreamLicenseClaim": null, "trademarkClearance": null, "evidenceNote": "Repository history shows a shared generic initial-badge pattern, but no immutable authorship or license evidence is recorded."}
|
||||
{"recordType": "asset", "path": "public/providers/novita.svg", "mediaType": "image/svg+xml", "sha256": "ab99ef3113a12e64ef8b44eda132094017359ede5bdb33e830ed855b69520612", "provenanceStatus": "proven", "source": {"kind": "git", "url": "https://github.com/GLINCKER/thesvg", "ref": "7870bc1c5f657d9accbb7f96cc457b8dd3363ee8", "path": "public/icons/novita/default.svg", "integrity": "sha256:ab99ef3113a12e64ef8b44eda132094017359ede5bdb33e830ed855b69520612", "match": "byte-exact"}, "upstreamLicenseClaim": {"value": "MIT", "assertedBy": "theSVG pinned registry", "evidence": "https://github.com/GLINCKER/thesvg/blob/7870bc1c5f657d9accbb7f96cc457b8dd3363ee8/src/data/icons.json", "independentlyVerified": false, "scope": "Upstream SVG copyright claim only; no trademark clearance.", "upstreamUrl": "https://novita.ai/"}, "trademarkClearance": null, "evidenceNote": "Local bytes are byte-identical to the pinned theSVG source. This proves source provenance only, not copyright or trademark clearance."}
|
||||
{"recordType": "asset", "path": "public/providers/nube.svg", "mediaType": "image/svg+xml", "sha256": "e5eff793cbc8a917e499c18365979f001010b229dd53b0802d5f29d9dfb963e1", "provenanceStatus": "probable", "source": null, "upstreamLicenseClaim": null, "trademarkClearance": null, "evidenceNote": "Repository PR #6926 describes this family as letter-in-circle placeholders, but original authorship and license were not independently proven."}
|
||||
@@ -90,7 +89,7 @@
|
||||
{"recordType": "asset", "path": "public/providers/openai.svg", "mediaType": "image/svg+xml", "sha256": "db81a8225166f02f773304ba4d8f0141343da5f43870d8b41f10bf6bc59840c8", "provenanceStatus": "proven", "source": {"kind": "git", "url": "https://github.com/GLINCKER/thesvg", "ref": "7870bc1c5f657d9accbb7f96cc457b8dd3363ee8", "path": "public/icons/openai/default.svg", "integrity": "sha256:db81a8225166f02f773304ba4d8f0141343da5f43870d8b41f10bf6bc59840c8", "match": "byte-exact"}, "upstreamLicenseClaim": {"value": "MIT", "assertedBy": "theSVG pinned registry", "evidence": "https://github.com/GLINCKER/thesvg/blob/7870bc1c5f657d9accbb7f96cc457b8dd3363ee8/src/data/icons.json", "independentlyVerified": false, "scope": "Upstream SVG copyright claim only; no trademark clearance.", "upstreamUrl": "https://openai.com/"}, "trademarkClearance": null, "evidenceNote": "Local bytes are byte-identical to the pinned theSVG source. This proves source provenance only, not copyright or trademark clearance."}
|
||||
{"recordType": "asset", "path": "public/providers/openclaw.svg", "mediaType": "image/svg+xml", "sha256": "4123c0c75dda5b28e3e0d38075514085bf546178a620776344813c08fa41277c", "provenanceStatus": "proven", "source": {"kind": "npm", "url": "https://registry.npmjs.org/@lobehub/icons/-/icons-5.10.0.tgz", "ref": "5.10.0", "path": "package/es/OpenClaw/components/Color.js", "integrity": "sha512-CIpjkISCLRK7haDtSugGFd0o3odaJts8ewJOkUiEFtns3xvsqbl8i24eowBnjw+yMDQVQyNONlhqTD58YC6Ljg==", "packageShasum": "add1baced073a60157d39c7820b8d5c1928a1054", "match": "svg-path-data", "matchDetail": "All 6/6 local SVG path d values match the pinned Color component."}, "upstreamLicenseClaim": {"value": "MIT", "assertedBy": "@lobehub/icons@5.10.0 package/LICENSE", "evidence": "https://registry.npmjs.org/@lobehub/icons/-/icons-5.10.0.tgz#package/LICENSE", "independentlyVerified": true, "scope": "Pinned package distribution only; no trademark clearance."}, "trademarkClearance": null, "evidenceNote": "All local SVG path data matches the pinned LobeHub Color component. This proves source provenance only, not trademark clearance."}
|
||||
{"recordType": "asset", "path": "public/providers/openrouter.svg", "mediaType": "image/svg+xml", "sha256": "d05021526e72fddf3426eabc066924aca83da0cd66a699a3de3bac58ed2fe0a2", "provenanceStatus": "proven", "source": {"kind": "git", "url": "https://github.com/GLINCKER/thesvg", "ref": "7870bc1c5f657d9accbb7f96cc457b8dd3363ee8", "path": "public/icons/openrouter/default.svg", "integrity": "sha256:d05021526e72fddf3426eabc066924aca83da0cd66a699a3de3bac58ed2fe0a2", "match": "byte-exact"}, "upstreamLicenseClaim": {"value": "CC0-1.0", "assertedBy": "theSVG pinned registry", "evidence": "https://github.com/GLINCKER/thesvg/blob/7870bc1c5f657d9accbb7f96cc457b8dd3363ee8/src/data/icons.json", "independentlyVerified": false, "scope": "Upstream SVG copyright claim only; no trademark clearance.", "upstreamUrl": "https://openrouter.ai/"}, "trademarkClearance": null, "evidenceNote": "Local bytes are byte-identical to the pinned theSVG source. This proves source provenance only, not copyright or trademark clearance."}
|
||||
{"recordType": "asset", "path": "public/providers/opper.svg", "mediaType": "image/svg+xml", "sha256": "e45d0409e7746946f204903ad6e7da267d805b7d7534fa684eeb7b8ac5717791", "provenanceStatus": "unresolved", "source": null, "upstreamLicenseClaim": null, "trademarkClearance": null, "evidenceNote": "Added by an unrelated already-merged provider PR (#11620/#11629); no provenance research recorded yet. Flagged unresolved pending review, per schema v1 (non-blocking)."}
|
||||
{"recordType": "asset", "path": "public/providers/opper.svg", "mediaType": "image/svg+xml", "sha256": "e45d0409e7746946f204903ad6e7da267d805b7d7534fa684eeb7b8ac5717791", "provenanceStatus": "proven", "source": {"kind": "git", "url": "https://github.com/opper-ai/provider-omniroute", "ref": "9aacef7d6ae68d8d79f5aee042a25e9b646d2338", "path": "public/providers/opper.svg", "integrity": "sha256:e45d0409e7746946f204903ad6e7da267d805b7d7534fa684eeb7b8ac5717791", "match": "byte-exact"}, "upstreamLicenseClaim": {"value": "MIT", "assertedBy": "opper-ai/provider-omniroute LICENSE at the pinned commit", "evidence": "https://github.com/opper-ai/provider-omniroute/blob/9aacef7d6ae68d8d79f5aee042a25e9b646d2338/LICENSE", "independentlyVerified": true, "scope": "Pinned repository distribution only; no trademark clearance."}, "trademarkClearance": null, "evidenceNote": "Local bytes are byte-identical to the pinned official-organization repository source. The same commit carries an MIT license. This proves source and repository-license provenance only, not copyright or trademark clearance."}
|
||||
{"recordType": "asset", "path": "public/providers/orcarouter.svg", "mediaType": "image/svg+xml", "sha256": "06b36d030492901cada4c1e757b613c3ada340727d74f601fe407cfad7b529cf", "provenanceStatus": "probable", "source": null, "upstreamLicenseClaim": null, "trademarkClearance": null, "evidenceNote": "Repository PR #6926 describes this family as letter-in-circle placeholders, but original authorship and license were not independently proven."}
|
||||
{"recordType": "asset", "path": "public/providers/ovhcloud.svg", "mediaType": "image/svg+xml", "sha256": "ab65efec83d5106fa649e1f3ec5db98beb20ec6708158362844c912c34e1d31a", "provenanceStatus": "proven", "source": {"kind": "git", "url": "https://github.com/GLINCKER/thesvg", "ref": "7870bc1c5f657d9accbb7f96cc457b8dd3363ee8", "path": "public/icons/ovhcloud/default.svg", "integrity": "sha256:ab65efec83d5106fa649e1f3ec5db98beb20ec6708158362844c912c34e1d31a", "match": "byte-exact"}, "upstreamLicenseClaim": {"value": "brand-use", "assertedBy": "theSVG pinned registry", "evidence": "https://github.com/GLINCKER/thesvg/blob/7870bc1c5f657d9accbb7f96cc457b8dd3363ee8/src/data/icons.json", "independentlyVerified": false, "scope": "Upstream SVG copyright claim only; no trademark clearance.", "upstreamUrl": "https://ovhcloud.com"}, "trademarkClearance": null, "evidenceNote": "Local bytes are byte-identical to the pinned theSVG source. This proves source provenance only, not copyright or trademark clearance."}
|
||||
{"recordType": "asset", "path": "public/providers/perplexity.svg", "mediaType": "image/svg+xml", "sha256": "c7a4c847b6b3c0e8a10868d35b0b4a89727c03f8db3394060dcdb33c4b21c83b", "provenanceStatus": "probable", "source": null, "upstreamLicenseClaim": null, "trademarkClearance": null, "evidenceNote": "Repository PR #6317 and the asset structure indicate a likely source family, but no immutable upstream source or hash was proven."}
|
||||
|
||||
@@ -104,8 +104,9 @@
|
||||
"_rebaseline_2026_07_28_v3849_release": "75.5 -> 99 (+23.5). Aperto EXIGIDO pelo modo --require-tighten do ratchet: a métrica melhorou de verdade no ciclo v3.8.49. A causa é o workflow assíncrono de tradução, que finalmente alcançou o denominador em EN — as rebaselines anteriores (v3.8.39/.44/.47) foram todas afrouxamentos registrando o atraso das traduções, e agora ele foi pago. O coletor SUBTRAI os placeholders (present - placeholder em scripts/quality/collect-metrics.mjs), então os 317 marcadores __MISSING__ que esta release introduziu para o drift de valor já estão descontados dos 99 — o número é honesto, não inflado por placeholder. Medido pelo collect-metrics do CI no run 30404226939."
|
||||
},
|
||||
"deadExports": {
|
||||
"value": 500,
|
||||
"value": 377,
|
||||
"direction": "down",
|
||||
"_tighten_2026_09_01_pr_11950_rebase": "500 -> 377. Measured on PR #11950 after rebasing its unreachable-code cleanup onto release/v3.8.51 tip 4bcd8cee99a0: DEAD_EXPORTS=347 + DEAD_FILES=30 = DEAD_TOTAL=377 via node scripts/check/check-dead-code.mjs.",
|
||||
"_rebaseline_2026_08_19_v3850_basereds_9985": "415 -> 416. Measured on release/v3.8.50 tip 14a480453 during the #9985 base-red drain. Removed the 2 genuinely-dead symbols traced to a specific recent change (PR #10148, 2026-08-18): the unused src/lib/quota/providerCapabilities.ts file and the unused ProviderQuotaMonitor interface in providerQuotaTelemetry.ts (418 -> 416). The remaining +1 could not be attributed to a single recent commit after checking every dead-list entry touched since the 2026-08-14 baseline measurement (most are pre-existing debt on files edited for unrelated reasons); rebaselining the residual 1 rather than guessing at removals. Structural cleanup stays tracked in #3501.",
|
||||
"_rebaseline_2026_08_09_v3850_post_sweep": "227 -> 230. Measured by npm run check:dead-code on the unmodified release/v3.8.50 tip 382449d593 during the mandatory --full-ci pre-flight. The +3 is inherited cycle drift from the authorized merge sweep; this repair adds no production exports. Rebaseline records the actual tip so ci.yml quality-gate can run, while structural cleanup remains separate debt.",
|
||||
"_rebaseline_2026_07_01_v3843_release": "225->227 (+2). v3.8.43 cycle drift, surfaced in the Quality Ratchet job after eslintWarnings was rebaselined (check:dead-code runs there). 227 = measured by check:dead-code (knip) on the release tip 4635076eb. The 5 CI fixes add 0 dead exports: safeHttpHref in linkify.ts is module-local AND used (called by linkifyText); no new exports; test files are not scanned. Tighten via --update next cycle.",
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
{
|
||||
"_comment": "Catraca de test-discovery (check-test-discovery.mjs). Cada entrada e um arquivo de teste que NENHUM runner coleta (ele nunca roda) — divida congelada na auditoria 6A.1 (2026-06-09; 195 originais, 135 religados no node runner em 6A.1c). So pode DIMINUIR: religue o teste (ajustando o glob do runner ou movendo o arquivo) e remova a entrada via --update. NAO adicione novos orfaos — corrija o runner.",
|
||||
"_remaining_13": "13 orfaos restantes: 2 testes de API em settings + 1 snapshot de quota do DB; 4 golden-set + 1 benchmark + 1 teste live + 1 stress (deliberadamente manuais — decidir runner/gating); 3 integration/services (gated RUN_SERVICES_INT=1, sem runner CI).",
|
||||
"_remaining_10": "10 orfaos restantes: 4 golden-set + 1 benchmark + 1 teste live + 1 stress (deliberadamente manuais — decidir runner/gating); 3 integration/services (gated RUN_SERVICES_INT=1, sem runner CI).",
|
||||
"orphans": [
|
||||
"src/app/api/settings/__tests__/memory.test.ts",
|
||||
"src/app/api/settings/__tests__/settings.test.ts",
|
||||
"src/lib/db/__tests__/quotaSnapshots.test.ts",
|
||||
"tests/benchmarks/pipeline-accuracy.test.ts",
|
||||
"tests/golden-set/compression-caveman-v2.test.ts",
|
||||
"tests/golden-set/compression-quality.test.ts",
|
||||
@@ -13,7 +10,6 @@
|
||||
"tests/integration/services/cliproxy-coexistence.test.ts",
|
||||
"tests/integration/services/full-lifecycle.int.test.ts",
|
||||
"tests/integration/services/route-guard-services.int.test.ts",
|
||||
"tests/live/deepseek-web-live.test.ts",
|
||||
"tests/theoldllm-stress.test.ts"
|
||||
"tests/live/deepseek-web-live.test.ts"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,4 +1,30 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"reconciliations": []
|
||||
"reconciliations": [
|
||||
{
|
||||
"id": "provider-takedown-2026-08-30",
|
||||
"reason": "Operator of a third-party keyless service asked in writing (2026-08-30) that every reference to it be removed from OmniRoute, including release documentation. Bullets whose sole subject was that provider are dropped; bullets that mentioned it in passing are reworded without the name.",
|
||||
"baseChangelogSha256": "dba84d68ba25f539575ec8679b62f084d88b302c7b596c55a28017b481265ad7",
|
||||
"resultChangelogSha256": "6b3d4fe192d3694bbef4cb5ba0f4985a81e269a159041b5dd9f11fefb91c04d7",
|
||||
"removedBullets": [
|
||||
"- **[TS7] fix(types): preserve The Old LLM proxy contracts** ([#9850](https://github.com/diegosouzapw/OmniRoute/pull/9850), original [#9793](https://github.com/diegosouzapw/OmniRoute/pull/9793)) — thanks @backryun",
|
||||
"- **fix(api):** DeepSeek V4's native `max` reasoning tier is now reachable. DeepSeek accepts `reasoning_effort` `low`/`high`/`max` and maps `medium`/`xhigh` down to `high`, while OmniRoute's canonical vocabulary collapses `max` onto `xhigh` — so `{\"effort\":\"max\"}` silently resolved to `high` and the catalog never advertised a `max` tier (or its `<model>-max` variant). Following the existing `extendCodexGpt56EffortValues` precedent, the native tier is now preserved for `deepseek`/`ds` V4 models only; the global effort vocabulary is unchanged, routed namespaces (`openrouter/deepseek/…`, `tllm/deepseek_v4`, `oc/deepseek-v4-flash-free`) keep the canonical behavior, and an explicit client `reasoning_effort` still wins ([#10230](https://github.com/diegosouzapw/OmniRoute/pull/10230)) — thanks @Neuron-Mr-White",
|
||||
"- Honor provider proxies for The Old LLM Vercel blocks ([#7380](https://github.com/diegosouzapw/OmniRoute/pull/7380)) — thanks @JxnLexn",
|
||||
"- **fix(resilience):** a bare, unrecognized `403` from a no-credential (`authType:\"none\"`) provider like mimocode or theoldllm no longer permanently bans the connection ([#6315](https://github.com/diegosouzapw/OmniRoute/issues/6315), [#6345](https://github.com/diegosouzapw/OmniRoute/issues/6345)) — `classifyProviderError()`'s 403 branch only exempted `apikey` providers from the terminal `FORBIDDEN` classification, so these free/stateless proxies (no real account/credential to revoke) fell through to `FORBIDDEN` on the first unmatched 403 and got `isActive:false, testStatus:\"banned\"` with no cooldown or retry. The exemption now also covers `authType:\"none\"` providers, returning `null` (recoverable) so the existing connection-cooldown/retry layer handles it. Regression guard: `tests/unit/errorClassifier-noauth-403-6315.test.ts`.",
|
||||
"- **feat(providers):** refresh The Old LLM (Free) model catalog ([#5181](https://github.com/diegosouzapw/OmniRoute/issues/5181)) — seed the current free `/api/chatgpt` tier (GPT-5/5.1/5.2/5.3/5.4, o3/o4-mini, Gemini 3 Pro / 2.5 Pro / 2.0 Flash / 1.5 Flash, Claude 4.6 Opus/Sonnet & 4.5 Haiku, GPT-4o, Grok 4, DeepSeek V3/R1, Sonar Pro) while keeping the legacy alias IDs for saved-preference compatibility. Also fixes a latent routing bug: `mapModel()` now passes known upstream IDs through unchanged, so Gemini/o-series/Grok/DeepSeek/Sonar models no longer silently collapse onto `GPT_5_4`. Regression guard: `tests/unit/theoldllm-model-refresh-5181.test.ts`. (thanks @WslzGmzs)",
|
||||
"- **fix(provider-registry): add correct `contextLength` to theoldllm models** — fills in accurate context-window sizes for theoldllm's models. ([#4184](https://github.com/diegosouzapw/OmniRoute/pull/4184) — thanks @herjarsa)",
|
||||
"- **fix(theoldllm):** `X-Request-Token` generated server-side, dropping the Playwright dependency — replicates the site's client `rie()` token (djb2 hash + `oldllm-client-2026` seed + UA prefix + 8-hex `crypto.randomUUID` suffix) directly, so The Old LLM no longer needs a headless browser to mint tokens. ([#3491](https://github.com/diegosouzapw/OmniRoute/pull/3491) — thanks @borodulin / @diegosouzapw)",
|
||||
"- **fix(catalog):** imported/custom models on no-auth providers (e.g. The Old LLM) now appear in `GET /api/v1/models` and the Playground model selector — the eligibility gate required a DB connection row which no-auth providers never have, silently dropping every imported model for them. ([#3463](https://github.com/diegosouzapw/OmniRoute/pull/3463) — thanks @tjengbudi / @diegosouzapw)",
|
||||
"- **fix(theoldllm):** stop the `[502]: Body is unusable: Body has already been read` error on the cached-token path — the executor read the same upstream `Response` body with `.text()` twice; it now reads it once and only re-reads after a token-rejection refetch. (#3296 — thanks @onizukashonan14-png)",
|
||||
"- **fix(dashboard):** keep no-auth providers (opencode, duckduckgo-web, theoldllm, veoaifree-web) visible under the \"Show configured only\" filter — they never create a connection row (`stats.total === 0`) but are always usable and already appear in `/v1/models`, so the filter now treats `displayAuthType === \"no-auth\"` as configured. (#3290 — thanks @uniQta)",
|
||||
"- **theoldllm:** add The Old LLM — a free, Playwright-backed provider with dual-mode operation (cached browser token + direct fetch) bridged through a Vercel relay (#3217 — thanks @oyi77)"
|
||||
],
|
||||
"addedBullets": [
|
||||
"- **fix(api):** DeepSeek V4's native `max` reasoning tier is now reachable. DeepSeek accepts `reasoning_effort` `low`/`high`/`max` and maps `medium`/`xhigh` down to `high`, while OmniRoute's canonical vocabulary collapses `max` onto `xhigh` — so `{\"effort\":\"max\"}` silently resolved to `high` and the catalog never advertised a `max` tier (or its `<model>-max` variant). Following the existing `extendCodexGpt56EffortValues` precedent, the native tier is now preserved for `deepseek`/`ds` V4 models only; the global effort vocabulary is unchanged, routed namespaces (`openrouter/deepseek/…`, `oc/deepseek-v4-flash-free`) keep the canonical behavior, and an explicit client `reasoning_effort` still wins ([#10230](https://github.com/diegosouzapw/OmniRoute/pull/10230)) — thanks @Neuron-Mr-White",
|
||||
"- **fix(resilience):** a bare, unrecognized `403` from a no-credential (`authType:\"none\"`) provider like mimocode no longer permanently bans the connection ([#6315](https://github.com/diegosouzapw/OmniRoute/issues/6315), [#6345](https://github.com/diegosouzapw/OmniRoute/issues/6345)) — `classifyProviderError()`'s 403 branch only exempted `apikey` providers from the terminal `FORBIDDEN` classification, so these free/stateless proxies (no real account/credential to revoke) fell through to `FORBIDDEN` on the first unmatched 403 and got `isActive:false, testStatus:\"banned\"` with no cooldown or retry. The exemption now also covers `authType:\"none\"` providers, returning `null` (recoverable) so the existing connection-cooldown/retry layer handles it. Regression guard: `tests/unit/errorClassifier-noauth-403-6315.test.ts`.",
|
||||
"- **fix(catalog):** imported/custom models on no-auth providers now appear in `GET /api/v1/models` and the Playground model selector — the eligibility gate required a DB connection row which no-auth providers never have, silently dropping every imported model for them. ([#3463](https://github.com/diegosouzapw/OmniRoute/pull/3463) — thanks @tjengbudi / @diegosouzapw)",
|
||||
"- **fix(dashboard):** keep no-auth providers (opencode, duckduckgo-web, veoaifree-web) visible under the \"Show configured only\" filter — they never create a connection row (`stats.total === 0`) but are always usable and already appear in `/v1/models`, so the filter now treats `displayAuthType === \"no-auth\"` as configured. (#3290 — thanks @uniQta)"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -7,4 +7,4 @@ USER pwuser
|
||||
|
||||
EXPOSE 9223
|
||||
|
||||
CMD ["/bin/sh", "-lc", "node /opt/cdp-proxy.mjs & exec $(find /ms-playwright -path '*/chrome-linux/chrome' -type f | head -n 1) --headless=new --no-sandbox --disable-dev-shm-usage --remote-debugging-port=9222 --user-data-dir=/browser-profile about:blank"]
|
||||
CMD ["/bin/sh", "-lc", "node /opt/cdp-proxy.mjs & chrome_path=$(find /ms-playwright -path '*/chrome-linux*/chrome' -type f | head -n 1); test -n \"$chrome_path\"; exec xvfb-run -a --server-args='-screen 0 1920x1080x24 -nolisten tcp' \"$chrome_path\" --no-sandbox --disable-dev-shm-usage --remote-debugging-port=9222 --user-data-dir=/browser-profile about:blank"]
|
||||
|
||||
@@ -30,6 +30,7 @@ Simple guides for using OmniRoute — no technical background needed.
|
||||
- [USER_GUIDE.md](guides/USER_GUIDE.md) — daily usage of the dashboard and API.
|
||||
- [THINKING_BUDGET.md](guides/THINKING_BUDGET.md) — thinking/reasoning budget modes (passthrough vs auto-strip).
|
||||
- [FEATURES.md](guides/FEATURES.md) — dashboard feature gallery.
|
||||
- [CHAOS-MODE.md](guides/CHAOS-MODE.md) — multi-model parallel/collaborative execution (setup, permissions, API).
|
||||
- [TIERS.md](guides/TIERS.md) — OmniRoute tiers explained (user guide).
|
||||
- [USAGE_QUOTA_GUIDE.md](guides/USAGE_QUOTA_GUIDE.md) — usage, quota & spend tracking.
|
||||
- [COST_TRACKING.md](guides/COST_TRACKING.md) — cost and spend tracking.
|
||||
@@ -78,6 +79,7 @@ Lookup material — API surface, environment variables, CLI flags, provider cata
|
||||
|
||||
- [API_REFERENCE.md](reference/API_REFERENCE.md) — REST API endpoints and shapes.
|
||||
- [PROVIDER_REFERENCE.md](reference/PROVIDER_REFERENCE.md) — auto-generated provider catalog (do not edit by hand).
|
||||
- [REMOVED_PROVIDERS.md](reference/REMOVED_PROVIDERS.md) — providers removed at their operator's request; never reintroduce without written permission.
|
||||
- [PROVIDER_PLUGIN_MANIFEST.md](reference/PROVIDER_PLUGIN_MANIFEST.md) — sidecar-safe provider plugin contract for Bifrost and CLIProxyAPI migration.
|
||||
- [openapi.yaml](openapi.yaml) — OpenAPI spec for the public API.
|
||||
- [ENVIRONMENT.md](reference/ENVIRONMENT.md) — environment variables reference.
|
||||
@@ -202,7 +204,7 @@ Mermaid sources and exported SVG/PNG diagrams referenced from the docs above. Se
|
||||
|
||||
## i18n/
|
||||
|
||||
Translated mirrors of the documentation in 43 locales. See [i18n/README.md](i18n/README.md) for the supported language list.
|
||||
Translated mirrors of the documentation in 42 locales (plus the English originals — 43 languages in total). See [i18n/README.md](i18n/README.md) for the supported language list.
|
||||
|
||||
## screenshots/
|
||||
|
||||
|
||||
@@ -17,27 +17,27 @@ It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic acr
|
||||
|
||||
Core capabilities:
|
||||
|
||||
- OpenAI-compatible API surface for CLI/tools (351 providers, 104 executors)
|
||||
- OpenAI-compatible API surface for CLI/tools (352 providers, 106 executors)
|
||||
- Request/response translation across provider formats
|
||||
- Model combo fallback (multi-model sequence)
|
||||
- Structured combo steps (`provider + model + connection`) with runtime ordering by `compositeTiers`
|
||||
- Account-level fallback (multi-account per provider)
|
||||
- Quota preflight and quota-aware P2C account selection in the main chat path
|
||||
- OAuth + API-key provider connection management (22 OAuth provider modules)
|
||||
- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
|
||||
- Embedding generation via `/v1/embeddings` (18 providers)
|
||||
- Image generation via `/v1/images/generations` (10+ providers, 20+ models)
|
||||
- Audio transcription via `/v1/audio/transcriptions` (7 providers)
|
||||
- Audio transcription via `/v1/audio/transcriptions` (18 providers)
|
||||
- Text-to-speech via `/v1/audio/speech` (24 built-in providers)
|
||||
- Video generation via `/v1/videos/generations` (ComfyUI + SD WebUI)
|
||||
- Music generation via `/v1/music/generations` (ComfyUI)
|
||||
- Web search via `/v1/search` (5 providers)
|
||||
- Web search via `/v1/search` (20 providers)
|
||||
- Moderations via `/v1/moderations`
|
||||
- Reranking via `/v1/rerank`
|
||||
- Think tag parsing (`<think>...</think>`) for reasoning models
|
||||
- Response sanitization for strict OpenAI SDK compatibility
|
||||
- Role normalization (developer→system, system→user) for cross-provider compatibility
|
||||
- Structured output conversion (json_schema → Gemini responseSchema)
|
||||
- Local persistence for providers, keys, aliases, combos, settings, pricing (26 DB modules)
|
||||
- Local persistence for providers, keys, aliases, combos, settings, pricing (122 DB modules)
|
||||
- Usage/cost tracking and request logging
|
||||
- Optional cloud sync for multi-device/state sync
|
||||
- IP allowlist/blocklist for API access control
|
||||
@@ -58,7 +58,7 @@ Core capabilities:
|
||||
- Compliance audit logging with opt-out per API key
|
||||
- Eval framework for LLM quality assurance
|
||||
- Health dashboard with real-time provider circuit breaker status
|
||||
- MCP Server (87 tools) with 3 transports (stdio/SSE/Streamable HTTP)
|
||||
- MCP Server (110 tools) with 3 transports (stdio/SSE/Streamable HTTP)
|
||||
- A2A Server (JSON-RPC 2.0 + SSE) with skills and task lifecycle
|
||||
- Memory system (extraction, injection, retrieval, summarization)
|
||||
- Skills system (registry, executor, sandbox, built-in skills)
|
||||
@@ -330,14 +330,14 @@ OAuth provider modules (22 individual files under `src/lib/oauth/providers/`):
|
||||
## 5) Embedded Services (v3.8.4)
|
||||
|
||||
OmniRoute can install, supervise, and route to locally-running AI tool processes
|
||||
called **embedded services**. Two are shipped in v3.8.4: 9Router and CLIProxyAPI.
|
||||
called **embedded services**. Five are shipped: 9Router, CLIProxyAPI, Bifrost, Mux and Dario.
|
||||
|
||||
Architecture layers:
|
||||
|
||||
- **UI** (`/dashboard/providers/services`) — two-tab page with lifecycle controls,
|
||||
live log streaming, API key management, and (for 9Router) embedded native UI via
|
||||
an internal reverse proxy.
|
||||
- **API** (`/api/services/{name}/*`) — 8 endpoints for 9Router, 7 for CLIProxyAPI,
|
||||
- **API** (`/api/services/{name}/*`) — 11 endpoints for 9Router, 10 for CLIProxyAPI, 8 each for Bifrost / Mux / Dario,
|
||||
all classified **LOCAL_ONLY** (hard rule #17). A shared `GET /api/services/[name]/logs`
|
||||
SSE endpoint serves both services.
|
||||
- **Supervisor** (`src/lib/services/`) — generic `ServiceSupervisor` class wraps
|
||||
@@ -370,14 +370,18 @@ Key capabilities:
|
||||
**auto**, lkgp, context-optimized, context-relay, **fusion**, plus a fallback path) —
|
||||
auto is the headline addition in v3.8.0; `fusion` (panel fan-out + judge synthesis,
|
||||
`open-sse/services/fusion.ts`) is new in v3.8.36.
|
||||
- **9-factor scoring**: cost, latency p95, success rate, quota headroom, lockout
|
||||
proximity, breaker state, recent failures, model availability, and tag affinity.
|
||||
- **16-factor scoring**: quota, health, inverse cost, inverse latency, task fit and
|
||||
ten more. The canonical table of factors and their default weights lives in
|
||||
[`docs/routing/AUTO-COMBO.md`](../routing/AUTO-COMBO.md) — restating it here would
|
||||
give it a second place to go stale.
|
||||
- **Virtual factory** materializes ephemeral combos when no matching named combo
|
||||
exists, sourcing candidates from healthy active provider connections.
|
||||
- **Auto prefixes**: `auto/coding`, `auto/cheap`, `auto/fast`, `auto/offline`,
|
||||
`auto/smart`, `auto/lkgp` — each backed by a tuned weight profile.
|
||||
- **4 mode packs**: coding, fast, cheap, smart — shipped as preset weight
|
||||
configurations callable from the dashboard.
|
||||
- **6 mode packs**: `ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`,
|
||||
`reliability-first` and `chaos-mode` — preset weight configurations callable from
|
||||
the dashboard. (Not to be confused with the `auto/*` prefixes above, which are
|
||||
request-time variants.)
|
||||
|
||||
For full algorithmic detail (factor formulas, weight tuning), see
|
||||
[`docs/routing/AUTO-COMBO.md`](../routing/AUTO-COMBO.md).
|
||||
@@ -879,8 +883,8 @@ flowchart LR
|
||||
|
||||
- `open-sse/translator/index.ts`: translator registry and orchestration
|
||||
- Request translators: `open-sse/translator/request/*` (9 modules — `antigravity-to-openai`, `claude-to-gemini`, `claude-to-openai`, `gemini-to-openai`, `openai-responses`, `openai-to-claude`, `openai-to-cursor`, `openai-to-gemini`, `openai-to-kiro`)
|
||||
- Response translators: `open-sse/translator/response/*` (8 modules — `claude-to-openai`, `cursor-to-openai`, `gemini-to-claude`, `gemini-to-openai`, `kiro-to-openai`, `openai-responses`, `openai-to-antigravity`, `openai-to-claude`)
|
||||
- Helpers: `open-sse/translator/helpers/*` (8 modules — `claudeHelper`, `geminiHelper`, `geminiToolsSanitizer`, `maxTokensHelper`, `openaiHelper`, `responsesApiHelper`, `schemaCoercion`, `toolCallHelper`)
|
||||
- Response translators: `open-sse/translator/response/*` (11 modules — `claude-to-openai`, `cursor-to-openai`, `gemini-to-claude`, `gemini-to-openai`, `kiro-to-openai`, `openai-responses`, `openai-to-antigravity`, `openai-to-claude`, `openai-to-gemini`, `openai-to-gemini-sse`, `responsesToolItem`)
|
||||
- Helpers: `open-sse/translator/helpers/*` (12 modules — `claudeHelper`, `geminiHelper`, `geminiToolsSanitizer`, `jsonUtil`, `markdownBoundary`, `maxTokensHelper`, `openaiHelper`, `responsesApiHelper`, `schemaCoercion`, `strictSystemHoist`, `toolCallHelper`, `toolCallShim`)
|
||||
- Format constants: `open-sse/translator/formats.ts`
|
||||
- Bootstrap and registry: `open-sse/translator/bootstrap.ts`, `open-sse/translator/registry.ts`
|
||||
- Image-format helpers: `open-sse/translator/image/`
|
||||
|
||||
@@ -6,7 +6,7 @@ lastUpdated: 2026-06-28
|
||||
|
||||
# OmniRoute Codebase Documentation
|
||||
|
||||
> **Version:** v3.8.0
|
||||
> **Version:** v3.8.51
|
||||
> **Last updated:** 2026-06-28
|
||||
> **Audience:** Engineers contributing to OmniRoute or building integrations on top of it.
|
||||
>
|
||||
@@ -64,7 +64,7 @@ OmniRoute/
|
||||
├── _ideia/, _references/, _mono_repo/, _tasks/ Internal scratch / planning (not shipped)
|
||||
├── CLAUDE.md Repo rules for Claude Code
|
||||
├── AGENTS.md Deeper architecture reference for agents
|
||||
├── package.json v3.8.0, workspace root
|
||||
├── package.json v3.8.51, workspace root
|
||||
└── tsconfig.json Path aliases + core compiler options
|
||||
```
|
||||
|
||||
@@ -219,7 +219,7 @@ src/app/api/services/
|
||||
Corresponding dashboard UI:
|
||||
`src/app/(dashboard)/dashboard/providers/services/` — two-tab page (CLIProxyAPI + 9Router).
|
||||
Reverse proxy for 9Router embedded UI:
|
||||
`src/app/(dashboard)/dashboard/providers/services/[name]/embed/[...path]/route.ts`
|
||||
`src/app/(dashboard)/dashboard/providers/services/[name]/embed/[[...path]]/route.ts`
|
||||
|
||||
Deep-dive: `docs/frameworks/EMBEDDED-SERVICES.md`
|
||||
|
||||
@@ -315,7 +315,6 @@ Top-level files in `src/lib/`:
|
||||
|
||||
- The old `localDb.ts` barrel was removed — consumers import specific `src/lib/db/*` modules directly.
|
||||
- `proxyHealth.ts`, `proxyLogger.ts`, `tokenHealthCheck.ts`, `localHealthCheck.ts`
|
||||
- `oneproxyRotator.ts`, `oneproxySync.ts`
|
||||
- `apiBridgeServer.ts`, `cacheLayer.ts`, `semanticCache.ts`, `settingsCache.ts`
|
||||
- `cloudSync.ts`, `initCloudSync.ts`
|
||||
- `cloudflaredTunnel.ts`, `ngrokTunnel.ts`, `tailscaleTunnel.ts`
|
||||
@@ -349,10 +348,10 @@ Domain modules (each owns one or more tables): `apiKeys.ts`, `backup.ts`,
|
||||
`syncTokens.ts`, `tierConfig.ts`, `upstreamProxy.ts`, `versionManager.ts`,
|
||||
`webhooks.ts`.
|
||||
|
||||
`migrations/` holds 55 versioned `.sql` files (idempotent, transactional) and is
|
||||
`migrations/` holds 167 versioned `.sql` files (idempotent, transactional) and is
|
||||
executed by `migrationRunner.ts` at boot.
|
||||
|
||||
Tables created across the migrations (52 total):
|
||||
Tables created across the migrations (123 total):
|
||||
|
||||
`a`, `account_key_limits`, `api_keys`, `batches`, `call_logs`,
|
||||
`combo_adaptation_state`, `combos`, `command_code_auth_sessions`,
|
||||
@@ -422,12 +421,12 @@ Split into focused subdirectories:
|
||||
`bodySize.ts`, `colors.ts`, `appConfig.ts`, `config.ts`,
|
||||
`sidebarVisibility.ts`, `visionBridgeDefaults.ts`.
|
||||
- `validation/` — `schemas.ts` (~80 Zod schemas), `compressionConfigSchemas.ts`,
|
||||
`oneproxySchemas.ts`, `providerSchema.ts`, `settingsSchemas.ts`, `helpers.ts`.
|
||||
`providerSchema.ts`, `settingsSchemas.ts`, `helpers.ts`.
|
||||
- `contracts/` — public API contracts shipped to npm.
|
||||
- `types/` — shared TS types.
|
||||
- `utils/` — `circuitBreaker.ts`, `apiAuth.ts`, `apiKey.ts`, `apiKeyPolicy.ts`,
|
||||
`apiResponse.ts`, `api.ts`, `classify429.ts`, `cliCompat.ts`, `clipboard.ts`,
|
||||
`cloud.ts`, `cn.ts`, `cors.ts`, `costEstimator.ts`, `featureFlags.ts`,
|
||||
`api.ts`, `classify429.ts`, `cliCompat.ts`, `clipboard.ts`, `cloud.ts`, `cn.ts`,
|
||||
`cors.ts`, `featureFlags.ts`,
|
||||
`fetchTimeout.ts`, `formatting.ts`, `inputSanitizer.ts`, `logger.ts`,
|
||||
`machine.ts`, `machineId.ts`, `maskEmail.ts`, `modelCatalogSearch.ts`,
|
||||
`nodeRuntimeSupport.ts`, `parseApiKeys.ts`, `providerHints.ts`,
|
||||
@@ -450,12 +449,12 @@ open-sse/
|
||||
├── types.d.ts
|
||||
├── config/ Provider registries, header profiles, identity, …
|
||||
├── handlers/ Request handlers (chat, embeddings, audio, image, …)
|
||||
├── executors/ 108 provider-specific HTTP executors
|
||||
├── executors/ 106 provider-specific HTTP executors
|
||||
├── translator/ Format conversion (OpenAI ↔ Claude ↔ Gemini ↔ Cursor ↔ Kiro)
|
||||
├── transformer/ Responses API ↔ Chat Completions stream transformer
|
||||
├── services/ 80+ service modules (combos, fallback, quotas, identity, …)
|
||||
├── utils/ Streaming helpers, TLS client, AWS SigV4, proxy fetch, …
|
||||
└── mcp-server/ MCP server (3 transports, 31 scopes, 105 tools)
|
||||
└── mcp-server/ MCP server (3 transports, 33 scopes, 110 tools)
|
||||
```
|
||||
|
||||
### 4.1 `open-sse/handlers/`
|
||||
@@ -480,7 +479,7 @@ open-sse/
|
||||
|
||||
### 4.2 `open-sse/executors/`
|
||||
|
||||
104 provider executors, each extending `BaseExecutor` (`base.ts`):
|
||||
106 provider executors, each extending `BaseExecutor` (`base.ts`):
|
||||
|
||||
`antigravity`, `azure-openai`, `blackbox-web`, `cliproxyapi`,
|
||||
`chatgpt-web-codex`, `cloudflare-ai`, `codex`, `commandCode`, `cursor`, `default`, `devin-cli`,
|
||||
@@ -489,7 +488,7 @@ open-sse/
|
||||
(shared identity helper) and `index.ts` (registry).
|
||||
|
||||
> Note: providers not listed here are served by `default.ts` using the generic
|
||||
> OpenAI-compatible executor. The full provider catalog (351 providers) lives in
|
||||
> OpenAI-compatible executor. The full provider catalog (352 providers) lives in
|
||||
> `src/shared/constants/providers.ts`.
|
||||
|
||||
### 4.3 `open-sse/translator/`
|
||||
@@ -538,11 +537,11 @@ Highlights (full list under `open-sse/services/`):
|
||||
|
||||
### 4.6 `open-sse/mcp-server/`
|
||||
|
||||
- **31 registered tools** wired in `server.ts` (12 scoped under `schemas/tools.ts`,
|
||||
5 compression tools, 3 memory tools, 4 skills tools, plus advanced tools added
|
||||
through `advancedTools.ts`).
|
||||
- **110 unique tools** wired in `server.ts` (45 canonical in `schemas/tools.ts` +
|
||||
memory, skills, GitHub-skills, pool, gamification, plugin, Notion, Obsidian,
|
||||
local-corpus and compression modules — union counted by `countUniqueMcpTools`).
|
||||
- **3 transports**: stdio, HTTP Streamable, SSE.
|
||||
- **31 scopes** declared in `src/shared/constants/mcpScopes.ts`.
|
||||
- **33 scopes** enforced at runtime — base list in `src/shared/constants/mcpScopes.ts`, full set is the union of the scopes declared by each tool module.
|
||||
- Audit table: `mcp_tool_audit` (populated by `audit.ts`).
|
||||
- Files: `server.ts`, `index.ts`, `httpTransport.ts`, `audit.ts`, `scopeEnforcement.ts`,
|
||||
`runtimeHeartbeat.ts`, `descriptionCompressor.ts`, `schemas/{tools, a2a, audit, index}.ts`,
|
||||
@@ -585,7 +584,7 @@ electron/
|
||||
├── main.js Electron main process
|
||||
├── preload.js Preload bridge (contextIsolation enabled)
|
||||
├── types.d.ts
|
||||
├── package.json electron-builder config, version 3.8.0
|
||||
├── package.json electron-builder config, version 3.8.51
|
||||
├── README.md
|
||||
├── assets/ Build resources (icons, entitlements, …)
|
||||
├── node_modules/ Dedicated node_modules (better-sqlite3, electron-updater)
|
||||
@@ -637,7 +636,7 @@ Two binaries are exposed in `package.json` → `bin`:
|
||||
| `tests/unit/` | Unit tests via Node native test runner (1821 files, plus `api/`, `auth/`, `authz/` subdirs) |
|
||||
| `tests/integration/` | Cross-module + DB-state tests |
|
||||
| `tests/e2e/` | Playwright UI tests |
|
||||
| `tests/protocols-e2e/` | MCP/A2A protocol e2e |
|
||||
| `tests/e2e/protocol-clients.test.ts` | MCP/A2A protocol e2e |
|
||||
| `tests/translator/` | Translator-specific tests |
|
||||
| `tests/security/` | Security regressions |
|
||||
| `tests/load/` | Load / stress tests |
|
||||
|
||||
@@ -9,13 +9,13 @@ It describes each gate, what it validates, which CI job it runs in, whether it u
|
||||
a ratchet baseline or a pass/fail policy, and whether it blocks the build or is advisory.
|
||||
|
||||
For a short summary and the allowlist policy, see the "Quality Gates & Ratchets" section
|
||||
in `CLAUDE.md`. For the critical assessment, maturity classification, and tool-agnostic
|
||||
in `AGENTS.md`. For the critical assessment, maturity classification, and tool-agnostic
|
||||
replication plan of the same system, see the
|
||||
[Quality Gate Playbook](../ops/QUALITY_GATE_PLAYBOOK.md).
|
||||
|
||||
---
|
||||
|
||||
## Gate Inventory (~50 scripts)
|
||||
## Gate Inventory (~90 scripts)
|
||||
|
||||
Scripts live under `scripts/check/` (policy gates) and `scripts/quality/` (ratchet engine).
|
||||
The CI source of truth is `.github/workflows/ci.yml`.
|
||||
@@ -57,47 +57,50 @@ assertion weakening and other masking remain owned by the independently blocking
|
||||
|
||||
Runs on every PR to `main`. Blocks merge on failure.
|
||||
|
||||
| Script (`npm run ...`) | Validates | Blocking |
|
||||
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
|
||||
| `check:node-runtime` | Node.js version is within the supported range | Yes |
|
||||
| `check:cycles` | Circular imports — all `src/` + `open-sse/` modules | Yes |
|
||||
| `check:route-validation:t06` | Zod schemas present on all routes (Tier 6 policy) | Yes |
|
||||
| `check:any-budget:t11` | `@ts-expect-error // any` count does not exceed budget (Tier 11 catraca) | Yes |
|
||||
| `check:provider-consistency` | Every provider in `providers.ts` has a matching entry in `providerRegistry.ts` (and vice-versa, within the allowlist) | Yes |
|
||||
| `check:model-lifecycle` | The two hand-maintained routing tables do not point at retired models (#11503): `FITNESS_TABLE` (`taskFitness.ts`) scores no routable retired id, every `BUILT_IN_ALIASES` target is a live catalog model, and every retired id the catalog still routes is either forwarded or listed in `allowedRetiredInCatalog`. Offline — compares against the vendor snapshot `config/quality/model-lifecycle.json`, refreshed by hand with `npm run quality:refresh-model-lifecycle` (network; not wired into CI). `allowedRetiredInCatalog` is a burn-down ratchet: add an entry only with a tracking issue. | Yes |
|
||||
| `check:fetch-targets` | Every `fetch("/api/...")` in client-side `src/` resolves to a real `route.ts` | Yes |
|
||||
| `check:deps` | All `npm install`-able deps across every `package.json` in the repo are in `dependency-allowlist.json`; new unpinned or slopsquatted packages flagged | Yes |
|
||||
| `audit:deps` | `npm audit` (root + electron) — no high/critical advisories (overlaps osv `check:vuln-ratchet`; see Rationalization Backlog) | Yes |
|
||||
| `check:lockfile` | `package-lock.json` integrity — https registry, integrity hashes, no host overrides | Yes |
|
||||
| `check:licenses` | SPDX license allowlist for production dependencies | Yes |
|
||||
| `check:tracked-artifacts` | No build artifacts / committed `node_modules` symlinks (also runs in husky pre-commit; pre-push is intentionally light — #6716) | Yes |
|
||||
| `check:file-size` | No source file exceeds the per-extension cap (ratchet: frozen large files in `frozen` list) | Yes |
|
||||
| `check:error-helper` | Error responses in executors/handlers use `buildErrorBody()` / `sanitizeErrorMessage()` (Hard Rule #12) | Yes |
|
||||
| `check:migration-numbering` | Migration SQL files are sequentially numbered, no gaps or duplicates | Yes |
|
||||
| `check:public-creds` | No literal OAuth `client_id`/`client_secret` or Firebase Web keys outside `publicCreds.ts` (Hard Rule #11) | Yes |
|
||||
| `check:db-rules` | No raw SQL outside `src/lib/db/` modules; no barrel-imports from `localDb.ts` (Hard Rules #2/#5) | Yes |
|
||||
| `check:known-symbols` | Provider executors, routing strategies, and translators registered in their dispatch tables match the files on disk — no orphaned or undeclared symbols | Yes |
|
||||
| `check:route-guard-membership` | Every route that spawns a child process is classified by `isLocalOnlyPath()` (Hard Rules #15/#17) | Yes |
|
||||
| `check:test-discovery` | Every `*.test.ts` / `*.spec.ts` file in the repo is collected by at least one test runner (ratchet: orphan list in `test-discovery-baseline.json` can only shrink) | Yes |
|
||||
| `check:docs-sync` | CHANGELOG version, OpenAPI version, and `llm.txt` are in sync | Yes |
|
||||
| `typecheck:core` | TypeScript compilation without errors (advisory warnings only) | Yes |
|
||||
| `typecheck:noimplicit:core` | Strict `noImplicitAny` — forward-looking; many pre-existing call sites still need annotations | **Advisory** (`continue-on-error: true`) |
|
||||
| `check:dashboard-typecheck` | `tsc` scoped to `src/app/(dashboard)/**` (#7033) — `typecheck:core`'s curated 27-file allowlist does not include any dashboard TSX, and `next build` never type-checks it either (`next.config.mjs` sets `ignoreBuildErrors: true`), so orphaned-identifier regressions there (#6625/#6909) were invisible to CI. Diffs against a frozen per-file/per-TS-code count baseline (`config/quality/dashboard-typecheck-baseline.json`, same stale-enforcement pattern as `check:known-symbols`) — only NEW errors beyond the baselined count fail the gate; ratchet down with `--update` when a pre-existing error is fixed. | Yes |
|
||||
| Script (`npm run ...`) | Validates | Blocking |
|
||||
| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
|
||||
| `check:node-runtime` | Node.js version is within the supported range | Yes |
|
||||
| `check:cycles` | Circular imports — all `src/` + `open-sse/` modules | Yes |
|
||||
| `check:route-validation:t06` | Zod schemas present on all routes (Tier 6 policy) | Yes |
|
||||
| `check:any-budget:t11` | `@ts-expect-error // any` count does not exceed budget (Tier 11 catraca) | Yes |
|
||||
| `check:provider-consistency` | Every provider in `providers.ts` has a matching entry in `providerRegistry.ts` (and vice-versa, within the allowlist) | Yes |
|
||||
| `check:model-lifecycle` | The two hand-maintained routing tables do not point at retired models (#11503): `FITNESS_TABLE` (`taskFitness.ts`) scores no routable retired id, every `BUILT_IN_ALIASES` target is a live catalog model, and every retired id the catalog still routes is either forwarded or listed in `allowedRetiredInCatalog`. Offline — compares against the vendor snapshot `config/quality/model-lifecycle.json`, refreshed by hand with `npm run quality:refresh-model-lifecycle` (network; not wired into CI). `allowedRetiredInCatalog` is a burn-down ratchet: add an entry only with a tracking issue. | Yes |
|
||||
| `check:fetch-targets` | Every `fetch("/api/...")` in client-side `src/` resolves to a real `route.ts` | Yes |
|
||||
| `check:deps` | All `npm install`-able deps across every `package.json` in the repo are in `dependency-allowlist.json`; new unpinned or slopsquatted packages flagged | Yes |
|
||||
| `audit:deps` | `npm audit` (root + electron) — no high/critical advisories (overlaps osv `check:vuln-ratchet`; see Rationalization Backlog) | Yes |
|
||||
| `check:lockfile` | `package-lock.json` integrity — https registry, integrity hashes, no host overrides | Yes |
|
||||
| `check:licenses` | SPDX license allowlist for production dependencies | Yes |
|
||||
| `check:tracked-artifacts` | No build artifacts / committed `node_modules` symlinks (also runs in husky pre-commit; pre-push is intentionally light — #6716) | Yes |
|
||||
| `check:file-size` | No source file exceeds the per-extension cap (ratchet: frozen large files in `frozen` list) | Yes |
|
||||
| `check:error-helper` | Error responses in executors/handlers use `buildErrorBody()` / `sanitizeErrorMessage()` (Hard Rule #12) | Yes |
|
||||
| `check:migration-numbering` | Migration SQL files are sequentially numbered, no gaps or duplicates | Yes |
|
||||
| `check:public-creds` | No literal OAuth `client_id`/`client_secret` or Firebase Web keys outside `publicCreds.ts` (Hard Rule #11) | Yes |
|
||||
| `check:db-rules` | No raw SQL outside `src/lib/db/` modules; no barrel-imports from `localDb.ts` (Hard Rules #2/#5) | Yes |
|
||||
| `check:known-symbols` | Provider executors, routing strategies, and translators registered in their dispatch tables match the files on disk — no orphaned or undeclared symbols | Yes |
|
||||
| `check:route-guard-membership` | Every route that spawns a child process is classified by `isLocalOnlyPath()` (Hard Rules #15/#17) | Yes |
|
||||
| `check:test-discovery` | Every `*.test.ts` / `*.spec.ts` file in the repo is collected by at least one test runner (ratchet: orphan list in `test-discovery-baseline.json` can only shrink) | Yes |
|
||||
| `check:agent-skills-sync` | Generated agent-skills artifacts match their source catalog (no drift) |
|
||||
| `check:provider-asset-provenance` | Provider logos/assets carry a recorded provenance entry |
|
||||
| `lint:json` | JSON config files parse and satisfy the repo lint rules |
|
||||
| `typecheck:core` | TypeScript compilation without errors (advisory warnings only) | Yes |
|
||||
| `typecheck:noimplicit:core` | Strict `noImplicitAny` — forward-looking; many pre-existing call sites still need annotations | **Advisory** (`continue-on-error: true`) |
|
||||
| `check:dashboard-typecheck` | `tsc` scoped to `src/app/(dashboard)/**` (#7033) — `typecheck:core`'s curated 27-file allowlist does not include any dashboard TSX, and `next build` never type-checks it either (`next.config.mjs` sets `ignoreBuildErrors: true`), so orphaned-identifier regressions there (#6625/#6909) were invisible to CI. Diffs against a frozen per-file/per-TS-code count baseline (`config/quality/dashboard-typecheck-baseline.json`, same stale-enforcement pattern as `check:known-symbols`) — only NEW errors beyond the baselined count fail the gate; ratchet down with `--update` when a pre-existing error is fixed. | Yes |
|
||||
|
||||
### Job: `quality-gate`
|
||||
|
||||
Runs after `test-coverage`. Blocks merge on failure.
|
||||
|
||||
| Script | Validates | Blocking |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------- |
|
||||
| `quality:collect` | Emits `quality-metrics.json` (ESLint warning count, coverage from merged shard report) | Yes (upstream of ratchet) |
|
||||
| `quality:ratchet` | Each metric in `quality-baseline.json` has not regressed (ESLint warnings ≤ baseline; coverage ≥ baseline) | Yes |
|
||||
| `check:duplication` | Code duplication (jscpd@4) does not exceed baseline in `quality-baseline.json` | Yes |
|
||||
| `check:complexity` | File-level cyclomatic complexity does not exceed the cap (core ESLint `complexity` + `max-lines-per-function`) | Yes |
|
||||
| `check:cognitive-complexity` | Cognitive complexity ratchet (`eslint-plugin-sonarjs`) — separate ESLint pass; mergeable with `check:complexity` (see Backlog) | Yes |
|
||||
| `check:dead-code` | Unused exports / files ratchet (knip) does not regress vs baseline | Yes |
|
||||
| `check:type-coverage` | Percent-typed ratchet (`type-coverage`) does not regress; largely subsumes `typecheck:noimplicit:core` | Yes |
|
||||
| `check:codeql-ratchet` | Open CodeQL alert count does not regress (reads via `gh api`; graceful-skip without token) | Yes |
|
||||
| Script | Validates | Blocking |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
|
||||
| `quality:collect` | Emits `quality-metrics.json` (ESLint warning count, coverage from merged shard report) | Yes (upstream of ratchet) |
|
||||
| `quality:ratchet` | Each metric in `quality-baseline.json` has not regressed (ESLint warnings ≤ baseline; coverage ≥ baseline) | Yes |
|
||||
| `check:duplication` | Code duplication (jscpd@4) does not exceed baseline in `quality-baseline.json` | Yes |
|
||||
| `check:complexity` | File-level cyclomatic complexity does not exceed the cap (core ESLint `complexity` + `max-lines-per-function`) | Yes |
|
||||
| `check:cognitive-complexity` | Cognitive complexity ratchet (`eslint-plugin-sonarjs`) — separate ESLint pass; CI runs both merged as the single `check:complexity-ratchets` step | Yes |
|
||||
| `check:dead-code` | Unused exports / files ratchet (knip) does not regress vs baseline | Yes |
|
||||
| `check:compression-budget` | Compression benchmark budget — per-engine token-savings floors must not regress | Yes |
|
||||
| `check:type-coverage` | Percent-typed ratchet (`type-coverage`) does not regress; largely subsumes `typecheck:noimplicit:core` | Yes |
|
||||
| `check:codeql-ratchet` | Open CodeQL alert count does not regress (reads via `gh api`; graceful-skip without token) | Yes |
|
||||
|
||||
### Job: `quality-extended`
|
||||
|
||||
@@ -208,7 +211,7 @@ Runs after `build`. Blocks merge on failure.
|
||||
|
||||
| Suite | Validates | Blocking |
|
||||
| ---------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| `test:vitest` | MCP server (109 tools), autoCombo, cache — vitest runner | Yes |
|
||||
| `test:vitest` | MCP server (110 tools), autoCombo, cache — vitest runner | Yes |
|
||||
| `test:vitest:ui` | UI component tests — vitest runner | **Blocking** — pre-existing failures are explicitly excluded in `vitest.config.ts`; new failures fail the job |
|
||||
|
||||
### Nightly workflows (scheduled, advisory)
|
||||
@@ -221,6 +224,8 @@ These run on a cron schedule (and `workflow_dispatch`), never on PRs. All are ad
|
||||
| `nightly-resilience` | heap-growth gate, chaos fault-injection, k6 load/soak | **Advisory** |
|
||||
| `nightly-llm-security` | promptfoo injection guard (block mode) + garak probes (skipped without a provider secret) | **Advisory** |
|
||||
| `nightly-schemathesis` | OpenAPI contract fuzzing (schemathesis) against a live OmniRoute using `docs/openapi.yaml` — surfaces spec violations / unhandled 500s (Fase 8 B.4) | **Advisory** |
|
||||
| `nightly-mutation` | Stryker mutation-testing score over the fast unit lane — surviving mutants surface weak asserts | **Advisory** |
|
||||
| `nightly-compat` | Node engine compatibility matrix across the supported `engines.node` ranges | **Advisory** |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ OmniRoute/
|
||||
├── bin/ # CLI entry point and command handlers
|
||||
├── scripts/ # Build, check, sync, and one-off scripts
|
||||
├── docs/ # Public documentation (you are here)
|
||||
├── tests/ # All test suites (unit, integration, e2e, protocols-e2e)
|
||||
├── tests/ # All test suites (unit, integration, e2e, protocol clients)
|
||||
├── public/ # Next.js static assets, PWA manifest, service worker, icons
|
||||
├── config/ # Static config + quality-gate state (i18n, payloadRules, quality/)
|
||||
├── images/ # Marketing / README image assets
|
||||
@@ -117,11 +117,11 @@ OmniRoute/
|
||||
```
|
||||
src/
|
||||
├── app/ # App Router (pages + API routes + status pages + landing)
|
||||
├── lib/ # Core libraries / domain modules (~50 subdirs + ~30 top-level files)
|
||||
├── lib/ # Core libraries / domain modules (80 subdirs + ~70 top-level files)
|
||||
├── domain/ # Pure domain logic (policy engine, fallback, cost, lockout, comboResolver, assessment)
|
||||
├── server/ # Server-only modules (authz pipeline, cors, auth middleware) — cannot import from client
|
||||
├── shared/ # Shared between server and client where safe (constants, types, validation, contracts, utils)
|
||||
├── i18n/ # next-intl config + per-locale message JSON (30+ locales)
|
||||
├── i18n/ # next-intl config + per-locale message JSON (43 locales)
|
||||
├── middleware/ # Next.js middleware (request enrichment, locale detection)
|
||||
├── mitm/ # MITM proxy core: cert gen/install, handlers, targets, inspector, masks, passthrough
|
||||
│ ├── handlers/ # 9 IDE-agent handler classes extending MitmHandlerBase (antigravity, kiro, copilot, codex, cursor, zed, claudeCode, openCode, trae)
|
||||
@@ -148,9 +148,8 @@ src/
|
||||
| `app/api/tools/traffic-inspector/` | Traffic Inspector REST + WS API — 16+ routes (requests, sessions, hosts, capture-modes, export, ws). LOCAL_ONLY + SPAWN_CAPABLE. See `docs/frameworks/TRAFFIC_INSPECTOR.md §8`. |
|
||||
| `app/a2a/` | A2A JSON-RPC 2.0 entry point (`POST /a2a`) |
|
||||
| `app/.well-known/agent.json/` | A2A Agent Card (discovery) |
|
||||
| `app/(dashboard)/dashboard/` | Dashboard UI pages (~35 pages: providers, combos, settings, memory, skills, webhooks, evals, audit, batch, cache, costs, health, system, activity, etc.) |
|
||||
| `app/(dashboard)/dashboard/` | Dashboard UI pages (50+ sections, ~118 page.tsx files: providers, combos, settings, memory, skills, webhooks, evals, audit, batch, cache, costs, health, system, activity, etc.) |
|
||||
| `app/(dashboard)/dashboard/search-tools/` | Search Tools Studio UI (3 tabs: Search/Scrape/Compare + SearchConceptCard + ProviderCatalog) — see `docs/frameworks/SEARCH_TOOLS_STUDIO.md` |
|
||||
| `app/(dashboard)/dashboard/` | Dashboard UI pages (~30 pages: providers, combos, settings, memory, skills, webhooks, evals, audit, batch, cache, costs, health, system, etc.) |
|
||||
| `app/(dashboard)/dashboard/memory/` | Memory Studio (plan 21): `page.tsx` (3-tab shell), `components/` (MemoryConceptCard, MemoryEngineStatus, EmbeddingSourceSelector, EditMemoryModal, RetrievePreview, QdrantConfigCard, RerankConfigCard), `components/tabs/` (MemoriesTab, PlaygroundTab, EngineTab), `hooks/` (useEngineStatus, useMemorySettings) |
|
||||
| `app/(dashboard)/dashboard/tools/agent-bridge/` | AgentBridge dashboard page — server card, 9 agent cards, setup wizard, model mapping, bypass list. i18n PT-BR + EN. See `docs/frameworks/AGENTBRIDGE.md`. |
|
||||
| `app/(dashboard)/dashboard/tools/traffic-inspector/` | Traffic Inspector dashboard page — DevTools split, 7 detail tabs, 4 capture mode toggles, session recorder, context colorization. i18n PT-BR + EN. See `docs/frameworks/TRAFFIC_INSPECTOR.md`. |
|
||||
@@ -181,7 +180,7 @@ src/
|
||||
| `compliance/` | Audit log + provider audit — see `docs/security/COMPLIANCE.md` |
|
||||
| `compression/` | Compression engine glue (engines live in `open-sse/services/compression/`) |
|
||||
| `config/` | Runtime config helpers |
|
||||
| `db/` | 95+ domain DB modules + 148 migrations (always go through here for SQLite) |
|
||||
| `db/` | 120+ domain DB modules + 167 migrations (always go through here for SQLite) |
|
||||
| `quota/` | Quota Sharing Engine: `dimensions.ts` (types/Zod), `types.ts` (QuotaStore interface), `sqliteQuotaStore.ts`, `redisQuotaStore.ts`, `storeFactory.ts`, `fairShare.ts`, `burnRate.ts`, `planResolver.ts`, `planRegistry.ts`, `saturationSignals.ts`, `enforce.ts`, `spendRecorder.ts` — see `docs/routing/QUOTA_SHARE.md` |
|
||||
| `radar/` | Radar free-model catalog client: `feedSchema.ts`, `pinnedKeys.ts`, `verify.ts`, `sync.ts`, `applyFeed.ts`, `index.ts` (`getRadarCatalog()`) — see `docs/frameworks/RADAR.md` |
|
||||
| `display/` | UI formatting helpers (cost, latency, etc.) |
|
||||
@@ -202,13 +201,12 @@ src/
|
||||
| `playground/` | Playground Studio shared helpers: `codeExport.ts` (curl/Python/TS generator), `promptImprover.ts` (meta-prompt builder), `streamMetrics.ts` (pure TTFT/TPS), `types.ts` (pricing table) — see `docs/frameworks/PLAYGROUND_STUDIO.md` |
|
||||
| `webhookDispatcher.ts` | HMAC webhook delivery — see `docs/frameworks/WEBHOOKS.md` |
|
||||
| `cloudflaredTunnel.ts`, `ngrokTunnel.ts` | Tunnel managers — see `docs/ops/TUNNELS_GUIDE.md` |
|
||||
| `oneproxySync.ts`, `oneproxyRotator.ts` | 1proxy free proxy marketplace — see `docs/ops/PROXY_GUIDE.md` |
|
||||
| `cloudSync.ts`, `initCloudSync.ts` | Optional cloud sync of state |
|
||||
| `localDb.ts` | Re-export barrel for db modules (no logic — re-exports only) |
|
||||
| `cacheLayer.ts`, `idempotencyLayer.ts` | Request caching + idempotency |
|
||||
| (~30 more top-level files) | Specialized helpers (logEnv, modelsDevSync, piiSanitizer, etc.) |
|
||||
|
||||
### `src/db/` — Database (117 modules + 148 migrations)
|
||||
### `src/lib/db/` — Database (122 modules + 167 migrations)
|
||||
|
||||
| Subdir | Purpose |
|
||||
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
@@ -220,16 +218,16 @@ src/
|
||||
|
||||
### `src/domain/`
|
||||
|
||||
| Module | Purpose |
|
||||
| ---------------------- | ----------------------------------------------------------------------- |
|
||||
| `policy.ts` | Policy engine |
|
||||
| `fallbackPolicy.ts` | Fallback decision tree |
|
||||
| `costRules.ts` | Cost calculation rules |
|
||||
| `lockoutPolicy.ts` | Model/connection lockout policy |
|
||||
| `tagRouter.ts` | Tag-based routing |
|
||||
| `comboResolver.ts` | Combo resolution (used by combo engine) |
|
||||
| `modelAvailability.ts` | Per-model availability check |
|
||||
| `assessment/` | Model assessment (Phase 1 of RFC-AUTO-ASSESSMENT — see `docs/archive/`) |
|
||||
| Module | Purpose |
|
||||
| ---------------------- | -------------------------------------------------- |
|
||||
| `policy.ts` | Policy engine |
|
||||
| `fallbackPolicy.ts` | Fallback decision tree |
|
||||
| `costRules.ts` | Cost calculation rules |
|
||||
| `lockoutPolicy.ts` | Model/connection lockout policy |
|
||||
| `tagRouter.ts` | Tag-based routing |
|
||||
| `comboResolver.ts` | Combo resolution (used by combo engine) |
|
||||
| `modelAvailability.ts` | Per-model availability check |
|
||||
| `assessment/` | Model assessment (Phase 1 of RFC-AUTO-ASSESSMENT ) |
|
||||
|
||||
### `src/server/`
|
||||
|
||||
@@ -243,7 +241,7 @@ src/
|
||||
|
||||
| Module | Purpose |
|
||||
| -------------------------------- | ---------------------------------------------------------------------- |
|
||||
| `constants/providers.ts` | **338 providers** with Zod validation (source of truth) |
|
||||
| `constants/providers.ts` | **352 providers** with Zod validation (source of truth) |
|
||||
| `constants/cliTools.ts` | External CLI tool registry |
|
||||
| `constants/routingStrategies.ts` | **19 routing strategies** with priorities |
|
||||
| `constants/publicApiRoutes.ts` | Routes that require Bearer (vs management) auth |
|
||||
@@ -270,7 +268,7 @@ open-sse/
|
||||
├── translator/ # Format converters (9 request, 9 response, 9 helpers)
|
||||
├── transformer/ # Responses API ↔ Chat Completions (TransformStream)
|
||||
├── services/ # ~80+ service modules (combo, accountFallback, autoCombo, reasoningCache, claude code/chatgpt stealth, modelDeprecation, taskAwareRouter, workflowFSM, etc.)
|
||||
├── mcp-server/ # MCP server (109 tools, 3 transports, 33 scopes)
|
||||
├── mcp-server/ # MCP server (110 tools, 3 transports, 33 scopes)
|
||||
├── config/ # Provider/model registries, header config, model aliases
|
||||
├── utils/ # TLS client, proxy fetch/dispatcher, network helpers
|
||||
├── index.ts # Workspace entry
|
||||
@@ -379,7 +377,7 @@ open-sse/
|
||||
|
||||
---
|
||||
|
||||
## `docs/` — Public Documentation (44 files + 4 subdirs)
|
||||
## `docs/` — Public Documentation (7 root files + 17 subdirs)
|
||||
|
||||
### Top-level guides
|
||||
|
||||
@@ -392,7 +390,7 @@ open-sse/
|
||||
| `API_REFERENCE.md` | API endpoint reference with auth model |
|
||||
| `openapi.yaml` | OpenAPI 3.0 spec (121 paths) |
|
||||
| `SETUP_GUIDE.md` | Install methods (npm, npx, Docker, Electron, Termux, source) |
|
||||
| `ENVIRONMENT.md` | All env vars (~219 used in code, ~810 lines `.env.example`) |
|
||||
| `ENVIRONMENT.md` | All env vars (~800 documented, ~3,050 lines `.env.example`) |
|
||||
| `TROUBLESHOOTING.md` | Common errors + v3.8.0 known issues |
|
||||
| `RELEASE_CHECKLIST.md` | Full release flow (skills, husky, conventional commits, deploy) |
|
||||
| `COVERAGE_PLAN.md` | Coverage goals and current state |
|
||||
@@ -400,28 +398,28 @@ open-sse/
|
||||
| `CLI-TOOLS.md` | External CLI integrations + Internal OmniRoute CLI |
|
||||
| `I18N.md` | i18n architecture, adding a language, 43 locales |
|
||||
| `UNINSTALL.md` | Clean uninstall steps |
|
||||
| `PROVIDER_REFERENCE.md` | **Auto-generated** catalog of 338 providers (regen: `npm run gen:provider-reference`) |
|
||||
| `PROVIDER_REFERENCE.md` | **Auto-generated** catalog of 352 providers (regen: `npm run gen:provider-reference`) |
|
||||
|
||||
### Subsystem deep-dives
|
||||
|
||||
| Doc | Purpose |
|
||||
| -------------------------- | ------------------------------------------------------------------- |
|
||||
| `MCP-SERVER.md` | MCP server: 109 tools, 3 transports, 33 scopes, REST endpoints |
|
||||
| `A2A-SERVER.md` | A2A v0.3: JSON-RPC, 6 skills, REST helpers, agent card |
|
||||
| `AGENT_PROTOCOLS_GUIDE.md` | Unified guide: A2A vs ACP vs Cloud Agents |
|
||||
| `CLOUD_AGENT.md` | Codex Cloud / Devin / Jules orchestration |
|
||||
| `SKILLS.md` | Skills framework (built-in + marketplace + SkillsSH + sandbox) |
|
||||
| `RADAR.md` | Radar free-model catalog overlay (`RADAR_ENABLED`, off by default) |
|
||||
| `MEMORY.md` | Memory system (SQLite FTS5 + Qdrant) |
|
||||
| `EVALS.md` | Eval framework (suites, runs, rubrics) |
|
||||
| `GUARDRAILS.md` | PII masker, prompt injection, vision bridge |
|
||||
| `COMPLIANCE.md` | Audit log, retention, noLog opt-out |
|
||||
| `WEBHOOKS.md` | HMAC-signed webhook delivery |
|
||||
| `REASONING_REPLAY.md` | Hybrid memory/SQLite cache for `reasoning_content` |
|
||||
| `AUTHZ_GUIDE.md` | Authorization pipeline (`classify` → `policies` → `enforce`) |
|
||||
| `RESILIENCE_GUIDE.md` | Circuit breaker + cooldown + model lockout |
|
||||
| `STEALTH_GUIDE.md` | TLS fingerprinting (JA3/JA4), Claude Code CCH, MITM cert |
|
||||
| `AUTO-COMBO.md` | Auto Combo engine (9-factor scoring, 4 mode packs, virtual factory) |
|
||||
| Doc | Purpose |
|
||||
| -------------------------- | -------------------------------------------------------------------- |
|
||||
| `MCP-SERVER.md` | MCP server: 110 tools, 3 transports, 33 scopes, REST endpoints |
|
||||
| `A2A-SERVER.md` | A2A v0.3: JSON-RPC, 6 skills, REST helpers, agent card |
|
||||
| `AGENT_PROTOCOLS_GUIDE.md` | Unified guide: A2A vs ACP vs Cloud Agents |
|
||||
| `CLOUD_AGENT.md` | Codex Cloud / Devin / Jules orchestration |
|
||||
| `SKILLS.md` | Skills framework (built-in + marketplace + SkillsSH + sandbox) |
|
||||
| `RADAR.md` | Radar free-model catalog overlay (`RADAR_ENABLED`, off by default) |
|
||||
| `MEMORY.md` | Memory system (SQLite FTS5 + Qdrant) |
|
||||
| `EVALS.md` | Eval framework (suites, runs, rubrics) |
|
||||
| `GUARDRAILS.md` | PII masker, prompt injection, vision bridge |
|
||||
| `COMPLIANCE.md` | Audit log, retention, noLog opt-out |
|
||||
| `WEBHOOKS.md` | HMAC-signed webhook delivery |
|
||||
| `REASONING_REPLAY.md` | Hybrid memory/SQLite cache for `reasoning_content` |
|
||||
| `AUTHZ_GUIDE.md` | Authorization pipeline (`classify` → `policies` → `enforce`) |
|
||||
| `RESILIENCE_GUIDE.md` | Circuit breaker + cooldown + model lockout |
|
||||
| `STEALTH_GUIDE.md` | TLS fingerprinting (JA3/JA4), Claude Code CCH, MITM cert |
|
||||
| `AUTO-COMBO.md` | Auto Combo engine (16-factor scoring, 6 mode packs, virtual factory) |
|
||||
|
||||
### Compression
|
||||
|
||||
@@ -450,8 +448,7 @@ open-sse/
|
||||
|
||||
| Subdir | Purpose |
|
||||
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `docs/archive/` | Archived/historical docs (e.g., `RFC-AUTO-ASSESSMENT-DRAFT.md` — superseded by EVALS) |
|
||||
| `docs/i18n/` | Localized doc translations (~42 locales) |
|
||||
| `docs/i18n/` | Localized doc translations (42 locales) |
|
||||
| `docs/screenshots/` | Image assets for guides |
|
||||
| `_tasks/superpowers/` | Plans/specs from superpowers (`writing-plans`/`brainstorming`) + research — isolated, separately-versioned repo, gitignored by the main tree. See CLAUDE.md → "Planning & Research Artifacts". |
|
||||
|
||||
@@ -459,13 +456,13 @@ open-sse/
|
||||
|
||||
## `tests/` — Test Suites
|
||||
|
||||
| Subdir | Type | Runner |
|
||||
| ---------------------- | --------------------------------------- | --------------------------------------- |
|
||||
| `tests/unit/` | Unit tests (~500 files, fastest) | Node native test runner |
|
||||
| `tests/integration/` | Multi-module + DB integration tests | Node native test runner (concurrency 1) |
|
||||
| `tests/e2e/` | UI + workflow E2E | Playwright |
|
||||
| `tests/protocols-e2e/` | MCP + A2A real-client E2E | Custom protocol clients |
|
||||
| `tests/ecosystem/` | Provider integration (network-touching) | Node native test runner |
|
||||
| Subdir | Type | Runner |
|
||||
| ------------------------------------ | --------------------------------------- | --------------------------------------- |
|
||||
| `tests/unit/` | Unit tests (~4,800 files, fastest) | Node native test runner |
|
||||
| `tests/integration/` | Multi-module + DB integration tests | Node native test runner (concurrency 1) |
|
||||
| `tests/e2e/` | UI + workflow E2E | Playwright |
|
||||
| `tests/e2e/protocol-clients.test.ts` | MCP + A2A real-client E2E | Custom protocol clients |
|
||||
| `tests/e2e/ecosystem.test.ts` | Provider integration (network-touching) | Node native test runner |
|
||||
|
||||
---
|
||||
|
||||
@@ -505,7 +502,7 @@ Shipped configuration templates plus the committed quality-gate baselines
|
||||
| ---------------------------------- | -------------------------------------------------------------- |
|
||||
| `.github/workflows/` | GitHub Actions CI/CD workflows (lint, test, coverage, release) |
|
||||
| `.github/ISSUE_TEMPLATE/` | Bug/feature issue templates |
|
||||
| `.github/PULL_REQUEST_TEMPLATE.md` | PR template |
|
||||
| `.github/pull_request_template.md` | PR template |
|
||||
| `.github/dependabot.yml` | Dependency update config |
|
||||
|
||||
---
|
||||
|
||||
@@ -50,6 +50,25 @@ OmniRoute has three distinct but related resilience mechanisms. Each has a diffe
|
||||
|
||||
---
|
||||
|
||||
### Opt-in global Provider Cooldown (window gate)
|
||||
|
||||
A fourth, **opt-in** layer (`PROVIDER_COOLDOWN_ENABLED`, default **off**) keeps a
|
||||
cross-request memory of failing providers in
|
||||
`open-sse/services/providerCooldownTracker.ts`, consulted by combo target
|
||||
resolution so consecutive combo requests stop re-walking a provider that just
|
||||
failed. Provider-level entries honor the `PROVIDER_PROFILES` window gate:
|
||||
|
||||
| Profile | trips after (`providerFailureThreshold`) | inside (`providerFailureWindowMs`) | cools for (`providerCooldownMs`) |
|
||||
| ------- | ---------------------------------------: | ---------------------------------: | -------------------------------: |
|
||||
| OAuth | `10` | `15min` | `5min` |
|
||||
| API key | `15` | `30min` | `10min` |
|
||||
|
||||
Below the threshold the provider is **not** considered cooling; a success clears
|
||||
the window. Connection-level entries (`provider:connectionId`) keep the
|
||||
exponential `minRetryCooldownMs → maxRetryCooldownMs` backoff instead. Overrides:
|
||||
`OMNIROUTE_PROVIDER_BREAKER_{OAUTH,API_KEY}_{FAILURE_THRESHOLD,FAILURE_WINDOW_MS,COOLDOWN_MS}`.
|
||||
Regression guard: `tests/unit/provider-cooldown-window-gate.test.ts`.
|
||||
|
||||
## 2. Connection Cooldown
|
||||
|
||||
**Scope:** single provider connection/account/key.
|
||||
@@ -633,4 +652,4 @@ default `test:integration`, chaos and heap self-skip (without `RUN_CHAOS_INT`/`-
|
||||
|
||||
- [Architecture Guide](./ARCHITECTURE.md) — System architecture and internals
|
||||
- [User Guide](../guides/USER_GUIDE.md) — Providers, combos, CLI integration
|
||||
- [Auto-Combo Engine](../routing/AUTO-COMBO.md) — 13-factor scoring, mode packs
|
||||
- [Auto-Combo Engine](../routing/AUTO-COMBO.md) — 16-factor scoring, mode packs
|
||||
|
||||
@@ -11,33 +11,33 @@ Objective feature comparison vs popular open-source AI routers.
|
||||
> **Methodology**: Public repos audited 2026-Q2. Versions as listed.
|
||||
> Submit corrections via PR — we want this to be accurate.
|
||||
|
||||
| Feature | OmniRoute 3.8 | LiteLLM 1.x | OpenRouter (SaaS) | Portkey |
|
||||
| -------------------------------------------------- | :----------------------------------------------: | :------------: | :---------------: | :---------: |
|
||||
| **Providers** | **329** | ~100 | ~50 | ~30 |
|
||||
| **Free/no-auth catalog entries** | **155** | n/a | passthrough | n/a |
|
||||
| **Self-hostable** | ✅ | ✅ | ❌ | ⚠ paid |
|
||||
| **OAuth catalog entries** | **23** | partial | ❌ | ❌ |
|
||||
| **Auto-fallback combos** | **19 strategies** | priority-based | tier-based | weighted |
|
||||
| **Fusion (parallel panel + judge synthesis)** | ✅ | ❌ | ❌ | ❌ |
|
||||
| **Tier 1/2/3 fallback (subscription→cheap→free)** | ✅ + UI | manual | n/a | manual |
|
||||
| **Token compression** | 12-engine stack (RTK + Caveman + LLMLingua) | none | none | none |
|
||||
| **Multimodal generation (speech/music/video)** | ✅ | ❌ | passthrough | ❌ |
|
||||
| **Built-in MCP server** | ✅ 107 tools, 32 scopes | ❌ | ❌ | ❌ |
|
||||
| **A2A protocol** | ✅ 6 skills | ❌ | ❌ | ❌ |
|
||||
| **Memory (FTS5 + vector)** | ✅ | ❌ | ❌ | ❌ |
|
||||
| **Guardrails (PII, injection, vision)** | ✅ | partial | ❌ | ✅ paid |
|
||||
| **Cloud agent integrations** | Codex, Cursor, Devin, Jules | ❌ | ❌ | ❌ |
|
||||
| **Circuit breaker per provider** | ✅ 3-state, lazy recovery | basic | ❌ | ✅ |
|
||||
| **TLS fingerprint stealth (JA3/JA4)** | ✅ wreq-js | ❌ | ❌ | ❌ |
|
||||
| **Eval framework** | ✅ built-in | ❌ | ❌ | ⚠ paid |
|
||||
| **MITM proxy (intercepts Cursor/Antigravity)** | ✅ cross-platform | ❌ | ❌ | ❌ |
|
||||
| **CLI with system tray (no Electron)** | ✅ | ❌ | n/a | n/a |
|
||||
| **CLI machine-ID auto-auth** | ✅ | ❌ | n/a | n/a |
|
||||
| **Dashboard** | Next.js 16 | basic | proprietary | proprietary |
|
||||
| **i18n** | **43 locales** | ❌ | ❌ | ⚠ |
|
||||
| **Public agent skills (SKILL.md)** | ✅ 45 | ❌ | ❌ | ❌ |
|
||||
| **Tunnel support (Cloudflared, Tailscale, Ngrok)** | ✅ | ❌ | n/a | n/a |
|
||||
| **License** | MIT | MIT | proprietary | proprietary |
|
||||
| Feature | OmniRoute 3.8 | LiteLLM 1.x | OpenRouter (SaaS) | Portkey |
|
||||
| -------------------------------------------------- | :-----------------------------------------: | :------------: | :---------------: | :---------: |
|
||||
| **Providers** | **329** | ~100 | ~50 | ~30 |
|
||||
| **Free/no-auth catalog entries** | **155** | n/a | passthrough | n/a |
|
||||
| **Self-hostable** | ✅ | ✅ | ❌ | ⚠ paid |
|
||||
| **OAuth catalog entries** | **23** | partial | ❌ | ❌ |
|
||||
| **Auto-fallback combos** | **19 strategies** | priority-based | tier-based | weighted |
|
||||
| **Fusion (parallel panel + judge synthesis)** | ✅ | ❌ | ❌ | ❌ |
|
||||
| **Tier 1/2/3 fallback (subscription→cheap→free)** | ✅ + UI | manual | n/a | manual |
|
||||
| **Token compression** | 12-engine stack (RTK + Caveman + LLMLingua) | none | none | none |
|
||||
| **Multimodal generation (speech/music/video)** | ✅ | ❌ | passthrough | ❌ |
|
||||
| **Built-in MCP server** | ✅ 110 tools, 33 scopes | ❌ | ❌ | ❌ |
|
||||
| **A2A protocol** | ✅ 6 skills | ❌ | ❌ | ❌ |
|
||||
| **Memory (FTS5 + vector)** | ✅ | ❌ | ❌ | ❌ |
|
||||
| **Guardrails (PII, injection, vision)** | ✅ | partial | ❌ | ✅ paid |
|
||||
| **Cloud agent integrations** | Codex, Cursor, Devin, Jules | ❌ | ❌ | ❌ |
|
||||
| **Circuit breaker per provider** | ✅ 3-state, lazy recovery | basic | ❌ | ✅ |
|
||||
| **TLS fingerprint stealth (JA3/JA4)** | ✅ wreq-js | ❌ | ❌ | ❌ |
|
||||
| **Eval framework** | ✅ built-in | ❌ | ❌ | ⚠ paid |
|
||||
| **MITM proxy (intercepts Cursor/Antigravity)** | ✅ cross-platform | ❌ | ❌ | ❌ |
|
||||
| **CLI with system tray (no Electron)** | ✅ | ❌ | n/a | n/a |
|
||||
| **CLI machine-ID auto-auth** | ✅ | ❌ | n/a | n/a |
|
||||
| **Dashboard** | Next.js 16 | basic | proprietary | proprietary |
|
||||
| **i18n** | **43 locales** | ❌ | ❌ | ⚠ |
|
||||
| **Public agent skills (SKILL.md)** | ✅ 45 | ❌ | ❌ | ❌ |
|
||||
| **Tunnel support (Cloudflared, Tailscale, Ngrok)** | ✅ | ❌ | n/a | n/a |
|
||||
| **License** | MIT | MIT | proprietary | proprietary |
|
||||
|
||||
## When to choose OmniRoute
|
||||
|
||||
|
||||
@@ -182,22 +182,6 @@ With Stacked: 10K-2.5K tokens sent (78-95% eligible RTK+Caveman range
|
||||
|
||||
---
|
||||
|
||||
## Output Styles
|
||||
|
||||
Output styles inject a system prompt instruction to steer the model's writing style. They are defined in the output style catalog and support multiple languages and intensity levels (`lite`, `full`, `ultra`).
|
||||
|
||||
| Style | Description | Supported Languages | Levels |
|
||||
| --- | --- | --- | --- |
|
||||
| `terse-prose` | Drop filler/articles/hedging; keep technical substance exact. | `en`, `pt-BR`, `ja`, `id`, `vi` | `lite`, `full`, `ultra` |
|
||||
| `less-code` | YAGNI ladder: smallest working change, no unrequested abstractions. | `en`, `pt-BR`, `vi`, `ja`, `id` | `lite`, `full`, `ultra` |
|
||||
| `ponytail` | Lazy senior-dev discipline: climb the YAGNI ladder, fix root cause, smallest working diff. | `en`, `pt-BR`, `vi`, `ja`, `id` | `lite`, `full`, `ultra` |
|
||||
| `i-have-adhd` | Action-first output: next action leads, steps numbered, one concrete next step, no preamble. | `en`, `pt-BR`, `vi`, `ja`, `id` | `lite`, `full`, `ultra` |
|
||||
| `terse-cjk` | Classical-Chinese ultra-terse style (locale-gated to zh). | `zh` | `lite`, `full`, `ultra` |
|
||||
|
||||
Each level appends a shared boundary clause ensuring that code blocks, URLs, file paths, commands, and identifiers remain verbatim.
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
### Dashboard
|
||||
@@ -472,11 +456,11 @@ together and are injected in catalog order.
|
||||
|
||||
| Style | `id` | What it does | Instruction languages |
|
||||
| --- | --- | --- | --- |
|
||||
| Terse prose | `terse-prose` | Drop filler/articles/hedging; keep technical substance exact. Same text as the legacy caveman output mode (referenced, not re-typed). | en, pt-BR, ja, id |
|
||||
| Less code | `less-code` | YAGNI ladder: smallest working change, no unrequested abstractions. | en only (backlog: [#10426](https://github.com/diegosouzapw/OmniRoute/issues/10426)) |
|
||||
| Ponytail (lazy senior dev) | `ponytail` | "The best code is the code never written": reuse > rewrite, root cause > symptom, shortest working diff. | en, pt-BR, vi, ja, id |
|
||||
| I have ADHD (action-first) | `i-have-adhd` | Action first (command/path/snippet before prose), numbered bounded steps, ONE concrete next step, no preamble/recap/closers. Adapted from [ayghri/i-have-adhd](https://github.com/ayghri/i-have-adhd) (MIT). | en, pt-BR, vi, ja, id |
|
||||
| Terse CJK (文言) | `terse-cjk` | Classical-Chinese ultra-terse style. | zh (locale-gated: only offered when the detected language is `zh`) |
|
||||
| Terse prose | `terse-prose` | Drop filler/articles/hedging; keep technical substance exact. Same text as the legacy caveman output mode (referenced, not re-typed). | en, pt-BR, es, de, fr, it, ru, zh, ja, id, vi |
|
||||
| Less code | `less-code` | YAGNI ladder: smallest working change, no unrequested abstractions. | en, pt-BR, es, de, fr, it, ru, zh, ja, id, vi |
|
||||
| Ponytail (lazy senior dev) | `ponytail` | "The best code is the code never written": reuse > rewrite, root cause > symptom, shortest working diff. | en, pt-BR, es, de, fr, it, ru, zh, ja, id, vi |
|
||||
| I have ADHD (action-first) | `i-have-adhd` | Action first (command/path/snippet before prose), numbered bounded steps, ONE concrete next step, no preamble/recap/closers. Adapted from [ayghri/i-have-adhd](https://github.com/ayghri/i-have-adhd) (MIT). | en, pt-BR, es, de, fr, it, ru, zh, ja, id, vi |
|
||||
| Terse CJK (文言) | `terse-cjk` | Classical-Chinese ultra-terse style. | zh (locale-gated: only offered when the resolved language is `zh`) |
|
||||
|
||||
Every style ships three intensity levels — `lite`, `full`, `ultra` — and every level
|
||||
ends with the shared boundaries clause, which keeps code blocks, file paths, commands,
|
||||
@@ -508,7 +492,11 @@ the selection as:
|
||||
```
|
||||
|
||||
Back-compat: the legacy `outputMode: "caveman"` combo setting still works and maps to
|
||||
`terse-prose`, byte-identical to the old injection in all four legacy languages.
|
||||
`terse-prose`, byte-identical to the old injection in every legacy language.
|
||||
|
||||
Language selection: with `languageConfig.enabled` on, `autoDetect` picks the
|
||||
language of the latest user message (same detector as the input engines);
|
||||
turning `autoDetect` off pins `defaultLanguage`. Off → English.
|
||||
|
||||
The style × language matrix is pinned by
|
||||
`tests/unit/compression/output-styles-i18n-matrix.test.ts`: a new style cannot ship
|
||||
|
||||
@@ -583,7 +583,7 @@ persistence and telemetry all enumerate the catalog — there is no other list t
|
||||
The instruction text must be **static and deterministic** per
|
||||
`(id, level, language)` — `${SHARED_BOUNDARIES}` is the only interpolation allowed.
|
||||
2. **Translate it.** Ship at least a `pt-BR` block under `i18n`; `ponytail` and
|
||||
`i-have-adhd` (en, pt-BR, vi, ja, id) are the reference shape. A deliberately
|
||||
`i-have-adhd` (en, pt-BR, es, de, fr, it, ru, zh, ja, id, vi) are the reference shape. A deliberately
|
||||
single-language style sets `locale` instead (like `terse-cjk` → `zh`) and is then
|
||||
only offered under that locale.
|
||||
3. **Update the matrix guard** — add the style's languages to `BASELINE_LANGUAGES` in
|
||||
|
||||
@@ -13,10 +13,10 @@ Mermaid sources (`.mmd`) and exported SVGs for OmniRoute v3.8.0 architecture flo
|
||||
| Source | Exported | Used in |
|
||||
| ---------------------------------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------ |
|
||||
| [request-pipeline.mmd](./request-pipeline.mmd) | [SVG](./exported/request-pipeline.svg) | docs/architecture/ARCHITECTURE.md, docs/architecture/CODEBASE_DOCUMENTATION.md |
|
||||
| [auto-combo-12factor.mmd](./auto-combo-12factor.mmd) | [SVG](./exported/auto-combo-12factor.svg) | docs/routing/AUTO-COMBO.md |
|
||||
| [auto-combo-scoring.mmd](./auto-combo-scoring.mmd) | [SVG](./exported/auto-combo-scoring.svg) | docs/routing/AUTO-COMBO.md |
|
||||
| [resilience-3layers.mmd](./resilience-3layers.mmd) | [SVG](./exported/resilience-3layers.svg) | docs/architecture/RESILIENCE_GUIDE.md, CLAUDE.md |
|
||||
| [i18n-flow.mmd](./i18n-flow.mmd) | [SVG](./exported/i18n-flow.svg) | docs/guides/I18N.md |
|
||||
| [mcp-tools-107.mmd](./mcp-tools-107.mmd) | [SVG](./exported/mcp-tools-107.svg) | docs/frameworks/MCP-SERVER.md |
|
||||
| [mcp-tools.mmd](./mcp-tools.mmd) | [SVG](./exported/mcp-tools.svg) | docs/frameworks/MCP-SERVER.md |
|
||||
| [cloud-agent-flow.mmd](./cloud-agent-flow.mmd) | [SVG](./exported/cloud-agent-flow.svg) | docs/frameworks/CLOUD_AGENT.md |
|
||||
| [authz-pipeline.mmd](./authz-pipeline.mmd) | [SVG](./exported/authz-pipeline.svg) | docs/architecture/AUTHZ_GUIDE.md |
|
||||
| [db-schema-overview.mmd](./db-schema-overview.mmd) | [SVG](./exported/db-schema-overview.svg) | docs/architecture/CODEBASE_DOCUMENTATION.md |
|
||||
@@ -30,10 +30,10 @@ inside GitHub's `<img>` sandbox:
|
||||
| File | Used in | Notes |
|
||||
| ------------------------------------------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [tier-cascade.svg](./tier-cascade.svg) | README.md (root) | Animated 4-tier auto-fallback cascade (16s loop, 4 acts). Edit the SVG directly — there is no `.mmd` source. |
|
||||
| [pool-fair-share.svg](./pool-fair-share.svg) | README.md (root) | Animated key-pool fair-share quota (generous → strict, 16s loop). Edit the SVG directly — there is no `.mmd` source. |
|
||||
| [pool-fair-share.svg](./pool-fair-share.svg) | — (unused) | Animated key-pool fair-share quota (generous → strict, 16s loop). Edit the SVG directly — there is no `.mmd` source. |
|
||||
| [combo-always-on.svg](./combo-always-on.svg) | style reference | Animated priority-combo fallback (4 layers, 16s loop). Edit the SVG directly — there is no `.mmd` source. |
|
||||
| [cli-terminal.svg](./cli-terminal.svg) | README.md (root) | Compact half-height animated terminal (1200×350): 3 real CLI commands cycling with typewriter + scrolling subcommand ticker; first frame = completed providers screen. Edit the SVG directly — there is no `.mmd` source. |
|
||||
| [compression-pipeline.svg](./compression-pipeline.svg) | README.md (root) | Animated 10-engine compression funnel (8s loop). Edit the SVG directly — there is no `.mmd` source. |
|
||||
| [compression-pipeline.svg](./compression-pipeline.svg) | README.md (root) | Animated 12-engine compression funnel (8s loop). Edit the SVG directly — there is no `.mmd` source. |
|
||||
| [free-tier-budget.svg](./free-tier-budget.svg) | README.md (root) | Animated free-tier budget card (~1.51B/mo quantified headline, 20-pool budget bar, per-pool grid, signup credits, 10s loop). Edit the SVG directly — there is no `.mmd` source. |
|
||||
| [readme-hero.svg](./readme-hero.svg) | README.md (root) | Animated hero card (tagline, live provider/free-access headline, full-width compression bar demo, 6 stat chips). Edit the SVG directly — there is no `.mmd` source. |
|
||||
| [promise-pillars.svg](./promise-pillars.svg) | README.md (root) | Animated "The Promise" 6-pillar card (12s border-highlight sweep). Edit the SVG directly — there is no `.mmd` source. |
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
%% Auto-Combo 15-factor scoring
|
||||
%% Auto-Combo 16-factor scoring
|
||||
%% Reflects: open-sse/services/autoCombo/scoring.ts (DEFAULT_WEIGHTS, sum = 1.0)
|
||||
%% v3.8.50
|
||||
%% svg-title: OmniRoute Auto-Combo 15-factor scoring
|
||||
%% svg-title: OmniRoute Auto-Combo 16-factor scoring
|
||||
%% svg-description: Flow from an incoming request through eligible candidates, the 15 weighted scoring factors, descending score sort, top-N selection, and sequential dispatch.
|
||||
flowchart TB
|
||||
Request["Incoming request"] --> Candidates["Eligible candidates<br/>(provider × model × account)"]
|
||||
Candidates --> Score["Compute composite score<br/>per candidate"]
|
||||
|
||||
subgraph Factors["15-factor scoring weights (sum = 1.0)"]
|
||||
subgraph Factors["16-factor scoring weights (sum = 1.0)"]
|
||||
f1["quota (0.1429)"]
|
||||
f2["health (0.1605)"]
|
||||
f3["costInv (0.1429)"]
|
||||
@@ -1,12 +1,12 @@
|
||||
<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 (354 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 86 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"/>
|
||||
<rect x="0" y="0" width="1200" height="34" fill="#161b22"/>
|
||||
<path d="M 0 34 L 1200 34" stroke="#ffffff" stroke-opacity="0.08" stroke-width="1"/>
|
||||
<circle cx="24" cy="17" r="6" fill="#ff5f56"/><circle cx="46" cy="17" r="6" fill="#ffbd2e"/><circle cx="68" cy="17" r="6" fill="#27c93f"/>
|
||||
<text x="600" y="22" text-anchor="middle" font-family="Consolas, 'Courier New', monospace" font-size="13" fill="#71717a">omniroute — 85 top-level commands</text>
|
||||
<g font-family="Consolas, 'Courier New', monospace" font-size="17"><animate attributeName="opacity" values="1;0;0" keyTimes="0;0.006;1" dur="18s" repeatCount="indefinite"/><text x="64" y="66" fill="#F7F6FC">omniroute providers list</text><text x="40" y="100" font-weight="700" fill="#38bdf8">OmniRoute Providers</text><text x="40" y="128" fill="#a1a1aa">1f3a9c2e  anthropic   Claude Max 20x    <tspan fill='#22c55e'>active</tspan></text><text x="40" y="154" fill="#a1a1aa">8c2d5b1a  codex       Codex Pro (team)  <tspan fill='#22c55e'>active</tspan></text><text x="40" y="180" fill="#a1a1aa">f4e0a97b  glm         GLM Coding Plan   <tspan fill='#22c55e'>active</tspan></text><text x="40" y="206" fill="#a1a1aa">03bd6e5f  kimi        Kimi K2 free      <tspan fill='#22c55e'>active</tspan></text><text x="40" y="232" fill="#71717a">… 347 more providers</text></g><g opacity="1" font-family="Consolas, 'Courier New', monospace" font-size="17">
|
||||
<text x="600" y="22" text-anchor="middle" font-family="Consolas, 'Courier New', monospace" font-size="13" fill="#71717a">omniroute — 86 top-level commands</text>
|
||||
<g font-family="Consolas, 'Courier New', monospace" font-size="17"><animate attributeName="opacity" values="1;0;0" keyTimes="0;0.006;1" dur="18s" repeatCount="indefinite"/><text x="64" y="66" fill="#F7F6FC">omniroute providers list</text><text x="40" y="100" font-weight="700" fill="#38bdf8">OmniRoute Providers</text><text x="40" y="128" fill="#a1a1aa">1f3a9c2e  anthropic   Claude Max 20x    <tspan fill='#22c55e'>active</tspan></text><text x="40" y="154" fill="#a1a1aa">8c2d5b1a  codex       Codex Pro (team)  <tspan fill='#22c55e'>active</tspan></text><text x="40" y="180" fill="#a1a1aa">f4e0a97b  glm         GLM Coding Plan   <tspan fill='#22c55e'>active</tspan></text><text x="40" y="206" fill="#a1a1aa">03bd6e5f  kimi        Kimi K2 free      <tspan fill='#22c55e'>active</tspan></text><text x="40" y="232" fill="#71717a">… 348 more providers</text></g><g opacity="1" font-family="Consolas, 'Courier New', monospace" font-size="17">
|
||||
<animate attributeName="opacity" values="1;1;0;0" keyTimes="0;0.315;0.33;1" dur="18s" repeatCount="indefinite"/>
|
||||
<text x="40" y="66" fill="#22c55e">$</text>
|
||||
<g clip-path="url(#tw0)"><text x="64" y="66" fill="#F7F6FC">omniroute providers list</text></g>
|
||||
@@ -14,7 +14,7 @@
|
||||
<animate attributeName="x" calcMode="discrete" values="64;95;125;156;186;217;248;278;309;309" keyTimes="0.000;0.012;0.018;0.024;0.030;0.036;0.042;0.048;0.054;1" dur="18s" repeatCount="indefinite"/>
|
||||
<animate attributeName="opacity" values="0;0;1;0.2;1;0.2;1;0;0" keyTimes="0;0.011;0.012;0.022;0.032;0.042;0.052;0.074;1" dur="18s" repeatCount="indefinite"/>
|
||||
</rect>
|
||||
<text x="40" y="100" font-weight="700" fill="#38bdf8" opacity="0"><animate attributeName="opacity" calcMode="discrete" values="0;0;1" keyTimes="0;0.045;0.047" dur="18s" repeatCount="indefinite"/>OmniRoute Providers</text><text x="40" y="128" fill="#a1a1aa" opacity="0"><animate attributeName="opacity" calcMode="discrete" values="0;0;1" keyTimes="0;0.053;0.055" dur="18s" repeatCount="indefinite"/>1f3a9c2e  anthropic   Claude Max 20x    <tspan fill='#22c55e'>active</tspan></text><text x="40" y="154" fill="#a1a1aa" opacity="0"><animate attributeName="opacity" calcMode="discrete" values="0;0;1" keyTimes="0;0.061;0.063" dur="18s" repeatCount="indefinite"/>8c2d5b1a  codex       Codex Pro (team)  <tspan fill='#22c55e'>active</tspan></text><text x="40" y="180" fill="#a1a1aa" opacity="0"><animate attributeName="opacity" calcMode="discrete" values="0;0;1" keyTimes="0;0.069;0.07100000000000001" dur="18s" repeatCount="indefinite"/>f4e0a97b  glm         GLM Coding Plan   <tspan fill='#22c55e'>active</tspan></text><text x="40" y="206" fill="#a1a1aa" opacity="0"><animate attributeName="opacity" calcMode="discrete" values="0;0;1" keyTimes="0;0.077;0.079" dur="18s" repeatCount="indefinite"/>03bd6e5f  kimi        Kimi K2 free      <tspan fill='#22c55e'>active</tspan></text><text x="40" y="232" fill="#71717a" opacity="0"><animate attributeName="opacity" calcMode="discrete" values="0;0;1" keyTimes="0;0.085;0.08700000000000001" dur="18s" repeatCount="indefinite"/>… 347 more providers</text>
|
||||
<text x="40" y="100" font-weight="700" fill="#38bdf8" opacity="0"><animate attributeName="opacity" calcMode="discrete" values="0;0;1" keyTimes="0;0.045;0.047" dur="18s" repeatCount="indefinite"/>OmniRoute Providers</text><text x="40" y="128" fill="#a1a1aa" opacity="0"><animate attributeName="opacity" calcMode="discrete" values="0;0;1" keyTimes="0;0.053;0.055" dur="18s" repeatCount="indefinite"/>1f3a9c2e  anthropic   Claude Max 20x    <tspan fill='#22c55e'>active</tspan></text><text x="40" y="154" fill="#a1a1aa" opacity="0"><animate attributeName="opacity" calcMode="discrete" values="0;0;1" keyTimes="0;0.061;0.063" dur="18s" repeatCount="indefinite"/>8c2d5b1a  codex       Codex Pro (team)  <tspan fill='#22c55e'>active</tspan></text><text x="40" y="180" fill="#a1a1aa" opacity="0"><animate attributeName="opacity" calcMode="discrete" values="0;0;1" keyTimes="0;0.069;0.07100000000000001" dur="18s" repeatCount="indefinite"/>f4e0a97b  glm         GLM Coding Plan   <tspan fill='#22c55e'>active</tspan></text><text x="40" y="206" fill="#a1a1aa" opacity="0"><animate attributeName="opacity" calcMode="discrete" values="0;0;1" keyTimes="0;0.077;0.079" dur="18s" repeatCount="indefinite"/>03bd6e5f  kimi        Kimi K2 free      <tspan fill='#22c55e'>active</tspan></text><text x="40" y="232" fill="#71717a" opacity="0"><animate attributeName="opacity" calcMode="discrete" values="0;0;1" keyTimes="0;0.085;0.08700000000000001" dur="18s" repeatCount="indefinite"/>… 348 more providers</text>
|
||||
</g><g opacity="0" font-family="Consolas, 'Courier New', monospace" font-size="17">
|
||||
<animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.333;0.34800000000000003;0.648;0.663;1" dur="18s" repeatCount="indefinite"/>
|
||||
<text x="40" y="66" fill="#22c55e">$</text>
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user