Compare commits
1 Commits
release/v3
...
fix/10096-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff6d465140 |
62
.env.example
@@ -45,26 +45,6 @@ INITIAL_PASSWORD=CHANGEME
|
||||
# executor's on-disk thread-sticky session cache. Leave unset to rely on DATA_DIR.
|
||||
# OMNIROUTE_DATA_DIR=/var/lib/omniroute
|
||||
|
||||
# Escape hatch for the test-context DATA_DIR guard (#10428). A test run that never
|
||||
# chose a DATA_DIR is redirected to a throwaway temp dir so it cannot open the
|
||||
# operator's real database. Set to 1 only for a deliberate run against the real
|
||||
# DATA_DIR — never for CI. Used by: src/lib/dataPaths.ts
|
||||
# OMNIROUTE_ALLOW_DEFAULT_DATA_DIR=1
|
||||
|
||||
# Build provenance (#10427). OMNIROUTE_BUILD_SHA lets a container inject the artifact's git
|
||||
# SHA when the dist/BUILD_SHA sentinel is absent; it is also what `npm run build:release`
|
||||
# stamps. OMNIROUTE_RELEASE_REF is the ref the pack gate checks ancestry against, and
|
||||
# OMNIROUTE_ALLOW_CANARY_BUILD=1
|
||||
|
||||
# API key the canary-deploy smoke uses when the target gateway requires auth (#10429).
|
||||
# Used by: scripts/ops/deploy-canary.mjs — sent as `Authorization: Bearer` on the
|
||||
# /v1/chat/completions probe. Never needed by the server itself.
|
||||
# OMNIROUTE_SMOKE_API_KEY=sk-... records a deliberate off-release-line build instead of
|
||||
# failing it. Used by: scripts/build/buildProvenance.ts, src/lib/monitoring/buildSha.ts
|
||||
# OMNIROUTE_BUILD_SHA=abc1234
|
||||
# OMNIROUTE_RELEASE_REF=origin/main
|
||||
# OMNIROUTE_ALLOW_CANARY_BUILD=1
|
||||
|
||||
# Encryption key for SQLite database encryption at rest.
|
||||
# Used by: src/lib/db/encryption.ts — encrypts the entire SQLite database.
|
||||
# Generate: openssl rand -hex 32 | Leave empty to disable DB encryption.
|
||||
@@ -714,16 +694,6 @@ NEXT_PUBLIC_ENABLE_SOCKS5_PROXY=true
|
||||
# Allow OmniRoute to write CLI config files (token refresh, etc.).
|
||||
# CLI_ALLOW_CONFIG_WRITES=true
|
||||
|
||||
# Force container detection on (1/true) or off (0/false). Leave unset for auto-detect
|
||||
# via /.dockerenv, /run/.containerenv, cgroup markers, or KUBERNETES_SERVICE_HOST.
|
||||
# Used by: src/shared/utils/containerEnv.ts — gates ephemeral-home CLI config writes.
|
||||
# OMNIROUTE_CONTAINER=1
|
||||
|
||||
# Allow CLI-tool config writes into an unmounted container path anyway (default off).
|
||||
# Prefer host-side `omniroute configure` / Remote Mode, or a bind-mounted CLI_CONFIG_HOME.
|
||||
# CLI equivalent: --allow-container-write. Used by: src/shared/utils/containerEnv.ts
|
||||
# OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE=true
|
||||
|
||||
# Auto-sync CLI profile files after provider model discovery changes. OPT-IN, default OFF for
|
||||
# both. When enabled, writes only the tool's profile files (~/.codex/*.config.toml or
|
||||
# ~/.claude/profiles/<name>/settings.json); never changes the active/default config. Both also
|
||||
@@ -745,21 +715,6 @@ NEXT_PUBLIC_ENABLE_SOCKS5_PROXY=true
|
||||
# CLI_AUGGIE_BIN=auggie
|
||||
# AUGGIE_BIN=auggie
|
||||
|
||||
# ── ZCode (Z.ai GLM coding-plan CLI) local provider ──
|
||||
# The local "zcode" provider talks to the authenticated ZCode app-server over a
|
||||
# custom framed stdio protocol. Overrides below tune that stdio lifecycle.
|
||||
# ZCODE_BIN=zcode
|
||||
# ZCODE_ARGS=["--some-flag"]
|
||||
# ZCODE_CWD=
|
||||
# ZCODE_PROVIDER_ID=builtin:zai-coding-plan
|
||||
# ZCODE_SERVER_RUNTIME_ROOT=~/.zcode/server
|
||||
# ZCODE_SERVER_NODE=~/.zcode/server/node
|
||||
# ZCODE_SERVER_ENTRY=~/.zcode/server/zcode-server.cjs
|
||||
# ZCODE_STARTUP_TIMEOUT_MS=10000
|
||||
# ZCODE_RPC_TIMEOUT_MS=30000
|
||||
# ZCODE_TURN_TIMEOUT_MS=120000
|
||||
# ZCODE_POLL_INTERVAL_MS=250
|
||||
|
||||
# Override the Hermes Agent home directory (where OmniRoute reads/writes the
|
||||
# Hermes CLI config). Matches the env var the Hermes PowerShell installer sets
|
||||
# on Windows (%LOCALAPPDATA%\hermes); defaults to ~/.hermes when unset.
|
||||
@@ -2398,12 +2353,6 @@ APP_LOG_TO_FILE=true
|
||||
# intended to be published as `omniroute-secure`. See SECURITY.md.
|
||||
# OMNIROUTE_BUILD_PROFILE=full
|
||||
|
||||
# Skip emitting `.tar.gz` tarballs during optional-pack staging for the Electron
|
||||
# standalone tree (pack directories + optional-packs.index.json are still produced).
|
||||
# Used by the desktop release workflow to trim artifact upload size.
|
||||
# Default (when unset): 1 (tarballs emitted). Set to 0 to disable.
|
||||
# OMNIROUTE_OPTIONAL_PACK_TAR=1
|
||||
|
||||
# Electron smoke harness (used by scripts/dev/smoke-electron-packaged.mjs).
|
||||
# ELECTRON_SMOKE_URL=http://127.0.0.1:20128/login
|
||||
# ELECTRON_SMOKE_TIMEOUT_MS=45000
|
||||
@@ -2703,9 +2652,9 @@ QUOTA_STORE_DRIVER=sqlite
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# Optional add-on (feature flag RADAR_ENABLED, default off — see feature flag
|
||||
# settings, not an env var) that overlays a signed, freshly-curated free-model
|
||||
# catalog on top of the release baseline. The first four variables below are
|
||||
# optional overrides for a self-hosted/forked feed or supporter-key flow. The
|
||||
# fifth is an optional, default-free link to the owner's private operations panel. Used by:
|
||||
# catalog on top of the release baseline. All four variables below are optional
|
||||
# and only needed to point the client at a self-hosted/forked feed or
|
||||
# supporter-key flow instead of the default OmniRoute Radar service. Used by:
|
||||
# src/lib/radar/sync.ts, src/lib/radar/pinnedKeys.ts, src/lib/radar/links.ts.
|
||||
|
||||
# Base URL of the Radar feed service. Overrides the built-in default so forks
|
||||
@@ -2726,11 +2675,6 @@ QUOTA_STORE_DRIVER=sqlite
|
||||
# page). No pricing/value lives in this repo — only the link.
|
||||
# RADAR_SUPPORTER_PLANS_URL=https://radar.omniroute.online/planos
|
||||
|
||||
# Owner-only link to the private Radar operations panel. There is deliberately
|
||||
# no default: when unset or invalid, no "Radar Admin" navigation item exists.
|
||||
# Use HTTPS for a tunnel/tailnet URL, or HTTP only for an SSH loopback forward.
|
||||
# RADAR_ADMIN_URL=http://127.0.0.1:9351
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# 27. RELEASE v3.8.50 ADDITIONS
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
2
.github/pull_request_template.md
vendored
@@ -18,7 +18,7 @@ Vitest, the 60% coverage gate, and the production build all run in CI on this PR
|
||||
- [ ] `npm run lint`
|
||||
- [ ] Reconciled with the current active release base; focused checks rerun afterward
|
||||
- [ ] Production-code changes include a new or updated automated test in this PR
|
||||
- SonarQube is temporarily opt-in while the private project has no quota; it is not a PR gate.
|
||||
- [ ] SonarQube PR analysis is green or any remaining issues are explicitly documented below
|
||||
|
||||
## Tests Added Or Updated
|
||||
|
||||
|
||||
16
.github/workflows/ci.yml
vendored
@@ -697,12 +697,11 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
needs: build
|
||||
# WS1.5 (v3.8.49 plan): the Electron native-module path previously executed for
|
||||
# WS1.5 (v3.8.49 plan): the Electron rebuild/spawn path previously executed for
|
||||
# the FIRST time on the release tag — the v3.8.48 Windows bug (npx.cmd spawned
|
||||
# without shell, CVE-2024-27980 behavior change) could only surface at release.
|
||||
# windows-latest runs prepare:bundle (better-sqlite3 prebuild verification since
|
||||
# v13 — the node-gyp rebuild is gone) per release PR; ubuntu keeps the full
|
||||
# pack + headless smoke.
|
||||
# windows-latest runs prepare:bundle (the ABI rebuild + spawn plan) per release
|
||||
# PR; ubuntu keeps the full pack + headless smoke.
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -739,7 +738,7 @@ jobs:
|
||||
# precedent): its first-ever real run (2026-07-15, run 29457533565) died in
|
||||
# 0.7s with the error swallowed by pwsh — bash shell captures stderr and
|
||||
# continue-on-error keeps the heavy gate green while we harden it (#7336).
|
||||
- name: Prepare Electron standalone (Windows prebuild verification)
|
||||
- name: Prepare Electron standalone (Windows ABI rebuild + spawn path)
|
||||
if: runner.os == 'Windows'
|
||||
working-directory: electron
|
||||
continue-on-error: true
|
||||
@@ -999,10 +998,7 @@ jobs:
|
||||
name: SonarQube
|
||||
runs-on: ubuntu-latest
|
||||
needs: test-coverage
|
||||
# Temporarily opt-in: the private project currently has no Sonar quota.
|
||||
# Re-enable without another code change by setting the repository Actions
|
||||
# variable SONARQUBE_ENABLED=true after quota/project access is restored.
|
||||
if: ${{ vars.SONARQUBE_ENABLED == 'true' && !cancelled() && needs.test-coverage.result == 'success' }}
|
||||
if: ${{ !cancelled() && needs.test-coverage.result == 'success' }}
|
||||
env:
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
|
||||
@@ -1401,7 +1397,7 @@ jobs:
|
||||
echo "| i18n UI Coverage | $(status '${{ needs.i18n-ui-coverage.result }}') |" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "| i18n Glossary (zh-CN, ko) | $(status '${{ needs.i18n-glossary-zhcn.result }}') |" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "| PR Test Policy | $(status '${{ needs.pr-test-policy.result }}') |" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "| SonarQube (opt-in; disabled without SONARQUBE_ENABLED=true) | $(status '${{ needs.sonarqube.result }}') |" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "| SonarQube | $(status '${{ needs.sonarqube.result }}') |" >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
echo "" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "## 🏗️ Build" >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
4
.github/workflows/codeql.yml
vendored
@@ -22,10 +22,10 @@ jobs:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
|
||||
- uses: github/codeql-action/init@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
|
||||
with:
|
||||
languages: javascript-typescript
|
||||
queries: security-extended
|
||||
- uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
|
||||
- uses: github/codeql-action/analyze@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
|
||||
with:
|
||||
category: "/language:javascript-typescript"
|
||||
|
||||
2
.github/workflows/dast-smoke.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
with:
|
||||
node-version: "24"
|
||||
cache: npm
|
||||
- uses: ./.github/actions/npm-ci-retry
|
||||
- run: npm ci
|
||||
- name: Build CLI bundle
|
||||
env:
|
||||
OMNIROUTE_BUILD_BACKEND_ONLY: "1"
|
||||
|
||||
2
.github/workflows/docker-publish.yml
vendored
@@ -372,7 +372,7 @@ jobs:
|
||||
- name: Upload Trivy SARIF to Security tab
|
||||
if: needs.prepare.outputs.version != 'main'
|
||||
continue-on-error: true
|
||||
uses: github/codeql-action/upload-sarif@v4.37.6
|
||||
uses: github/codeql-action/upload-sarif@v4.37.4
|
||||
with:
|
||||
sarif_file: trivy-results.sarif
|
||||
category: trivy-image
|
||||
|
||||
116
.github/workflows/electron-release.yml
vendored
@@ -55,75 +55,9 @@ jobs:
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "✓ Valid version: $VERSION"
|
||||
|
||||
web-build:
|
||||
name: Build shared Next standalone
|
||||
needs: validate
|
||||
# Stage 8 (issue #10321): the four desktop legs used to each run the full
|
||||
# `npm run build` (Next standalone) — ~111 runner-minutes per release just to
|
||||
# produce the same platform-independent bundle four times. This job builds it
|
||||
# once on ubuntu; every leg then restores the byte-verified archive and
|
||||
# re-forks its native optionals (scripts/build/standaloneBundle.mjs).
|
||||
#
|
||||
# Rollback lever: set the repo variable ELECTRON_SHARED_STANDALONE=disabled.
|
||||
# This job then skips, every leg falls back to building its own web bundle
|
||||
# (the legacy step below), and the pipeline behaves exactly like pre-Stage 8 —
|
||||
# no revert needed.
|
||||
if: ${{ !cancelled() && needs.validate.result == 'success' && vars.ELECTRON_SHARED_STANDALONE != 'disabled' }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: 24
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
env:
|
||||
NPM_CONFIG_LEGACY_PEER_DEPS: true
|
||||
|
||||
- name: Build Next.js standalone
|
||||
# webpack, not Turbopack, for the same hosted-runner RAM reason as the
|
||||
# linux leg (see the long comment on the fallback step in `build`).
|
||||
env:
|
||||
JWT_SECRET: ci-build-secret-with-sufficient-length-for-validation
|
||||
NODE_OPTIONS: "--max_old_space_size=6144"
|
||||
OMNIROUTE_USE_TURBOPACK: "0"
|
||||
run: npm run build
|
||||
|
||||
- name: Pack standalone bundle
|
||||
# Deterministic tar.gz + byte-level manifest; the manifest embeds the
|
||||
# archive's own sha256 so artifact-transfer corruption is caught before
|
||||
# extraction, and every entry is re-verified after extraction.
|
||||
run: node scripts/build/standaloneBundle.mjs pack --out web-bundle.tar.gz
|
||||
|
||||
- name: Upload shared web bundle
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: web-standalone-bundle
|
||||
# compression-level 0: the payload is already a deterministic tar.gz;
|
||||
# re-zipping would only burn runner CPU without shrinking it further.
|
||||
compression-level: 0
|
||||
# Legs consume this within minutes; no reason to retain it like the
|
||||
# installer artifacts (default 90d).
|
||||
retention-days: 3
|
||||
path: |
|
||||
web-bundle.tar.gz
|
||||
web-bundle.tar.gz.manifest.json
|
||||
|
||||
build:
|
||||
name: Build Electron (${{ matrix.platform }})
|
||||
needs: [validate, web-build]
|
||||
# `web-build` is skipped when ELECTRON_SHARED_STANDALONE=disabled (rollback
|
||||
# mode); legs then run the legacy per-leg web build below. If it ran and
|
||||
# failed, fail closed: legs cannot package without the bundle, and silently
|
||||
# falling back to four per-leg builds would hide exactly the regression the
|
||||
# shared job exists to surface.
|
||||
if: ${{ !cancelled() && needs.validate.result == 'success' && (needs.web-build.result == 'success' || needs.web-build.result == 'skipped') }}
|
||||
needs: validate
|
||||
runs-on: ${{ matrix.runner }}
|
||||
permissions:
|
||||
contents: write # electron-builder may publish artifacts with GH_TOKEN
|
||||
@@ -135,27 +69,19 @@ jobs:
|
||||
runner: windows-latest
|
||||
target: win
|
||||
ext: .exe
|
||||
os: win32
|
||||
arch: x64
|
||||
- platform: macos-intel
|
||||
runner: macos-15-intel
|
||||
target: mac-x64
|
||||
ext: .dmg
|
||||
os: darwin
|
||||
arch: x64
|
||||
- platform: macos-arm64
|
||||
runner: macos-latest
|
||||
target: mac-arm64
|
||||
ext: -arm64.dmg
|
||||
os: darwin
|
||||
arch: arm64
|
||||
- platform: linux
|
||||
runner: ubuntu-latest
|
||||
target: linux
|
||||
ext: .AppImage
|
||||
deb_ext: .deb
|
||||
os: linux
|
||||
arch: x64,arm64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
@@ -167,6 +93,14 @@ jobs:
|
||||
node-version: 24
|
||||
cache: npm
|
||||
|
||||
- name: Cache node_modules
|
||||
uses: actions/cache@v6.1.0
|
||||
with:
|
||||
path: node_modules
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
env:
|
||||
@@ -182,11 +116,7 @@ jobs:
|
||||
mkdir -p "$RUNNER_TEMP/home"
|
||||
echo "USERPROFILE=$RUNNER_TEMP/home" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Build Next.js standalone (legacy per-leg fallback)
|
||||
# Stage 8: only runs in rollback mode (ELECTRON_SHARED_STANDALONE=disabled)
|
||||
# or when the shared web-build job was skipped. Otherwise the leg restores
|
||||
# the shared bundle from the `web-build` job below.
|
||||
if: needs.web-build.result == 'skipped'
|
||||
- name: Build Next.js standalone
|
||||
env:
|
||||
JWT_SECRET: ci-build-secret-with-sufficient-length-for-validation
|
||||
NODE_OPTIONS: "--max_old_space_size=6144"
|
||||
@@ -204,30 +134,6 @@ jobs:
|
||||
OMNIROUTE_USE_TURBOPACK: ${{ matrix.platform == 'linux' && '0' || '1' }}
|
||||
run: npm run build
|
||||
|
||||
- name: Download shared web bundle
|
||||
# Stage 8: inverse of the fallback step above — runs exactly when the
|
||||
# shared `web-build` job produced the bundle.
|
||||
if: needs.web-build.result == 'success'
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: web-standalone-bundle
|
||||
|
||||
- name: Restore + hydrate shared web bundle
|
||||
if: needs.web-build.result == 'success'
|
||||
shell: bash
|
||||
# restore: verify the archive's sha256 against the manifest, extract, then
|
||||
# re-verify every entry (existence + size + content hash + symlink
|
||||
# targets, and no unlisted files) byte-for-byte.
|
||||
# hydrate: the bundle was built on ubuntu, so install-machine-forked native
|
||||
# optionals (@img/sharp-*, @img/sharp-libvips-*, @ngrok/ngrok-*,
|
||||
# fsevents) carry linux forks. Replace them with the forks this
|
||||
# leg's own `npm ci` resolved, then assert every bundled native
|
||||
# (koffi triplets, better-sqlite3 prebuilds, wreq-js, onnxruntime)
|
||||
# can service this leg's platform/arch before packaging starts.
|
||||
run: |
|
||||
node scripts/build/standaloneBundle.mjs restore --archive web-bundle.tar.gz
|
||||
node scripts/build/standaloneBundle.mjs hydrate --platform ${{ matrix.os }} --arch ${{ matrix.arch }}
|
||||
|
||||
- name: Sync version in electron/package.json
|
||||
shell: bash
|
||||
env:
|
||||
@@ -252,7 +158,7 @@ jobs:
|
||||
|
||||
- name: Install Electron dependencies
|
||||
working-directory: electron
|
||||
run: npm ci --no-audit --no-fund
|
||||
run: npm install --no-audit --no-fund
|
||||
|
||||
- name: Build Electron for ${{ matrix.platform }}
|
||||
working-directory: electron
|
||||
|
||||
58
.github/workflows/quality.yml
vendored
@@ -60,49 +60,13 @@ jobs:
|
||||
build:
|
||||
name: Build (advisory)
|
||||
needs: changes
|
||||
# FORK PRs ONLY. build.yml's `Fast Production Build` triggers on `push: branches: ["**"]`
|
||||
# and runs `build:release` — a superset of this job — so for an own-origin branch this job
|
||||
# was building the same tree twice. A fork contributor pushes to THEIR repo, so that push
|
||||
# never fires here, and this is the only pre-merge build signal they get. Measured
|
||||
# 2026-08-14: 72 of the last 100 PRs into release/** came from forks, so the fork case is
|
||||
# the majority of the traffic, not the exception — this job earns its place, it just should
|
||||
# not duplicate build.yml for the own-origin 28%.
|
||||
if: ${{ github.event_name != 'pull_request' || ((github.event.pull_request.draft == false || startsWith(github.head_ref, 'mergify/merge-queue/')) && needs.changes.outputs.code == 'true' && github.event.pull_request.head.repo.full_name != github.repository) }}
|
||||
# PINNED to hosted — this was the last job in THIS workflow still on the USE_VPS_RUNNER
|
||||
# switch (ci.yml's Build, nightly-release-green and npm-publish keep it, so the variable
|
||||
# stays meaningful), and with USE_VPS_RUNNER=true it produced NO signal at all here.
|
||||
# Measured 2026-08-14 over the last 25
|
||||
# quality.yml runs: not one Build (advisory) reached a conclusion. Every sample was either
|
||||
# queued on the self-hosted pool (2 runners, `omniroute-113-6/7`, both permanently busy — one
|
||||
# job sat queued 2h+ and was still unclaimed) or, when it did land, killed mid-build by this
|
||||
# workflow's own `cancel-in-progress` concurrency. 6/6 sampled "failures" are exit 143 /
|
||||
# "The runner has received a shutdown signal" at ~3.5 min into `npm run build` — zero OOM,
|
||||
# zero build errors. So the job burned a scarce runner that the gates actually need while
|
||||
# reporting a permanent red on every PR.
|
||||
#
|
||||
# Gap 19 left USE_VPS_RUNNER governing build-like jobs on the premise that "the build needs
|
||||
# the .113's RAM". That premise no longer holds: `Fast Production Build` (build.yml) runs
|
||||
# `build:release` — a SUPERSET of this job's `npm run build`, plus the CLI bundle — on plain
|
||||
# ubuntu-latest and passed 24/25 of its last runs in ~15 min. What it has and this job did
|
||||
# not is memory PROVISIONING: a 10 GB swapfile plus a 12 GB V8 heap. That matters because
|
||||
# --max-old-space-size only bounds V8's JS heap, never Turbopack's native (Rust) allocation
|
||||
# (#6409) — swap is what absorbs the native peak. Both are mirrored below.
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name != 'pull_request' || ((github.event.pull_request.draft == false || startsWith(github.head_ref, 'mergify/merge-queue/')) && needs.changes.outputs.code == 'true') }}
|
||||
# Dynamic runner — same fork-safe rule as ci.yml / fast-gates.
|
||||
runs-on: ${{ (vars.USE_VPS_RUNNER == 'true' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)) && fromJSON('["self-hosted","omni-release"]') || 'ubuntu-latest' }}
|
||||
# #7307: advisory for the first week of release-PR runs; remove
|
||||
# continue-on-error after the production-build signal is stable.
|
||||
continue-on-error: true
|
||||
steps:
|
||||
# Mirrors build.yml: Turbopack's native peak is not bounded by --max-old-space-size, so
|
||||
# the hosted runner needs swap headroom before the build starts.
|
||||
- name: Expand virtual memory (10 GB swap)
|
||||
run: |
|
||||
sudo swapoff -a || true
|
||||
sudo rm -f /mnt/swapfile /swapfile
|
||||
sudo fallocate -l 10G /mnt/swapfile || sudo dd if=/dev/zero of=/mnt/swapfile bs=1M count=10240
|
||||
sudo chmod 600 /mnt/swapfile
|
||||
sudo mkswap /mnt/swapfile
|
||||
sudo swapon /mnt/swapfile
|
||||
free -h
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
@@ -115,10 +79,6 @@ jobs:
|
||||
- run: npm run build
|
||||
env:
|
||||
OMNIROUTE_USE_TURBOPACK: "1"
|
||||
# Same heap build.yml proves sufficient. build-next-isolated.mjs defaults to 8192 and
|
||||
# honours OMNIROUTE_BUILD_MEMORY_MB; NODE_OPTIONS is set for parity with build.yml.
|
||||
NODE_OPTIONS: "--max-old-space-size=12288"
|
||||
OMNIROUTE_BUILD_MEMORY_MB: "12288"
|
||||
# No artifact upload here: the PR-to-release quality workflow has no
|
||||
# downstream package/e2e jobs that consume the Next.js build output.
|
||||
|
||||
@@ -137,7 +97,7 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ env.CI_NODE_VERSION }}
|
||||
cache: npm
|
||||
- uses: ./.github/actions/npm-ci-retry
|
||||
- run: npm ci
|
||||
# One walk of src/app/api for openapi-routes + docs-symbols (both still fail independently).
|
||||
- run: npm run check:api-docs-refs
|
||||
- name: Docs accuracy (fabricated-docs + i18n mirrors, strict)
|
||||
@@ -181,7 +141,7 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ env.CI_NODE_VERSION }}
|
||||
cache: npm
|
||||
- uses: ./.github/actions/npm-ci-retry
|
||||
- run: npm ci
|
||||
- name: Restore ESLint file cache
|
||||
uses: actions/cache@v6
|
||||
with:
|
||||
@@ -430,7 +390,7 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ env.CI_NODE_VERSION }}
|
||||
cache: npm
|
||||
- uses: ./.github/actions/npm-ci-retry
|
||||
- run: npm ci
|
||||
# WS5.2/5.3: JUnit feeds Trunk Flaky Tests — the fast-path runs on EVERY PR,
|
||||
# which is where flaky-detection volume actually comes from (ci.yml's heavy
|
||||
# jobs only run on the release PR). Advisory upload, own-origin only.
|
||||
@@ -476,7 +436,7 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ env.CI_NODE_VERSION }}
|
||||
cache: npm
|
||||
- uses: ./.github/actions/npm-ci-retry
|
||||
- run: npm ci
|
||||
# QW-d: fonte única — o mesmo npm script do CI pesado/local. Fecha dois drifts do
|
||||
# comando inline antigo: os dirs `memory` e `usage` estavam FORA do glob (testes
|
||||
# silenciosamente não rodavam no fast path) e o setupPolyfill não era importado.
|
||||
@@ -516,7 +476,7 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ env.CI_NODE_VERSION }}
|
||||
cache: npm
|
||||
- uses: ./.github/actions/npm-ci-retry
|
||||
- run: npm ci
|
||||
- name: Restore ESLint file cache
|
||||
uses: actions/cache@v6
|
||||
with:
|
||||
@@ -583,7 +543,7 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ env.CI_NODE_VERSION }}
|
||||
cache: npm
|
||||
- uses: ./.github/actions/npm-ci-retry
|
||||
- run: npm ci
|
||||
- name: CHANGELOG integrity (nenhum bullet da base pode sumir no merge-result)
|
||||
run: npm run check:changelog-integrity
|
||||
- name: Agent-skills generator sync (SKILL.md gerado ≡ catálogo)
|
||||
|
||||
1
.gitignore
vendored
@@ -1,7 +1,6 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# project-specific directories
|
||||
/output/
|
||||
.slim/deepwork/
|
||||
.omnivscodeagent/
|
||||
omnirouteCloud/
|
||||
|
||||
@@ -14,11 +14,3 @@ open-sse/config/freeModelCatalog.data.ts
|
||||
# Prettier reformats the frontmatter (blank line after ---), which makes the gate
|
||||
# fail on any skill that happens to pass through lint-staged.
|
||||
skills/*/SKILL.md
|
||||
|
||||
# check:changelog-integrity compares release bullets against the base as exact
|
||||
# strings. Prettier normalizes markdown emphasis inside them (*from* -> _from_)
|
||||
# and re-wraps table rows, so any PR that stages CHANGELOG.md would "lose" base
|
||||
# bullets and turn the merge-integrity job red. The changelog is generated and
|
||||
# reconciled by scripts/release/*, which are its formatter of record.
|
||||
CHANGELOG.md
|
||||
docs/i18n/*/CHANGELOG.md
|
||||
|
||||
47
AGENTS.md
@@ -46,22 +46,22 @@ Repository map and Reference Documentation sections below.
|
||||
|
||||
## Project at a Glance
|
||||
|
||||
**OmniRoute** — unified AI proxy/router. One endpoint, 340 LLM providers, auto-fallback.
|
||||
**OmniRoute** — unified AI proxy/router. One endpoint, 339 LLM providers, auto-fallback.
|
||||
|
||||
| Layer | Location | Purpose |
|
||||
| ------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| API Routes | `src/app/api/v1/` | Next.js App Router — entry points |
|
||||
| Handlers | `open-sse/handlers/` | Request processing (chat, embeddings, etc) |
|
||||
| Executors | `open-sse/executors/` | Provider-specific HTTP dispatch |
|
||||
| Translators | `open-sse/translator/` | Format conversion (OpenAI↔Claude↔Gemini) |
|
||||
| Transformer | `open-sse/transformer/` | Responses API ↔ Chat Completions |
|
||||
| Services | `open-sse/services/` | Combo routing, rate limits, caching, etc |
|
||||
| Database | `src/lib/db/` | SQLite domain modules (148 migrations) |
|
||||
| Domain/Policy | `src/domain/` | Policy engine, cost rules, fallback logic |
|
||||
| MCP Server | `open-sse/mcp-server/` | 109 tools (44 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 |
|
||||
| Layer | Location | Purpose |
|
||||
| ------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| API Routes | `src/app/api/v1/` | Next.js App Router — entry points |
|
||||
| Handlers | `open-sse/handlers/` | Request processing (chat, embeddings, etc) |
|
||||
| Executors | `open-sse/executors/` | Provider-specific HTTP dispatch |
|
||||
| Translators | `open-sse/translator/` | Format conversion (OpenAI↔Claude↔Gemini) |
|
||||
| Transformer | `open-sse/transformer/` | Responses API ↔ Chat Completions |
|
||||
| Services | `open-sse/services/` | Combo routing, rate limits, caching, etc |
|
||||
| Database | `src/lib/db/` | SQLite domain modules (145 migrations) |
|
||||
| Domain/Policy | `src/domain/` | Policy engine, cost rules, fallback logic |
|
||||
| MCP Server | `open-sse/mcp-server/` | 105 tools (43 base + memory/skill/agentSkill/pool/notion/obsidian/gamification/plugin modules), 3 transports (stdio / SSE / Streamable HTTP), 31 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 |
|
||||
|
||||
Monorepo: `src/` (Next.js 16 app), `open-sse/` (streaming engine workspace), `electron/` (desktop app), `tests/`, `bin/` (CLI entry point).
|
||||
|
||||
@@ -118,18 +118,11 @@ upstream/service level, so one unhealthy provider does not slow down every reque
|
||||
- `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`):
|
||||
|
||||
| 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` |
|
||||
|
||||
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.
|
||||
- OAuth providers: threshold `3`, reset timeout `60s`.
|
||||
- API-key providers: threshold `5`, reset timeout `30s`.
|
||||
- Local providers: threshold `2`, reset timeout `15s`.
|
||||
|
||||
Only provider-level failure statuses should trip the provider breaker:
|
||||
|
||||
@@ -686,7 +679,7 @@ the stale-enforcement added in Fase 6A.3.
|
||||
causa-raiz de DOIS wipes (2026-08-08 e 2026-08-10: `git reset --hard` materializou o
|
||||
symlink rastreado por cima do diretório real e o git apagou todo o conteúdo ignorado sem
|
||||
aviso); (c) após qualquer escrita relevante, `git -C _tasks add -A && git -C _tasks commit
|
||||
&& git -C _tasks push` — o push frequente é o backup real; (d) repetir esta proibição
|
||||
&& git -C _tasks push` — o push frequente é o backup real; (d) repetir esta proibição
|
||||
VERBATIM no prompt de todo subagente que toque git; (e) se `_tasks` aparecer como symlink
|
||||
quebrado, NÃO commitar nada — restaurar do remote e avisar o operador. O gate
|
||||
`check:tracked-artifacts` (pre-commit + CI) bloqueia `_tasks` rastreado em qualquer forma.
|
||||
|
||||
121
CHANGELOG.md
@@ -148,22 +148,6 @@ _Living section — regenerated 2026-08-12 from all cycle commits (cycle open `e
|
||||
- **feat(admission) — direct pushes:** adaptive overload/pressure controls with shared admission wired across the LLM routes, plus mutation-test registration for the capability-filter suite
|
||||
- **feat(agentrouter) — direct pushes:** support Claude and Codex protocols — infer the protocol from the client endpoint and honor the alternate protocol through the chat pipeline
|
||||
- **feat(providers) — direct pushes:** ChatGPT Web session credential guide with a Cookie Editor fast-path (canonical chromewebstore install link) and web-session fast-path test coverage
|
||||
- **feat(sse):** honor provider-rule lock scope for agentrouter (connection vs model) ([#10419](https://github.com/diegosouzapw/OmniRoute/pull/10419))
|
||||
- **feat(ocr):** Vertex AI DeepSeek-OCR provider ([#10398](https://github.com/diegosouzapw/OmniRoute/pull/10398))
|
||||
- **feat(providers):** derive imageToText from the OCR registry + chutes dots.ocr seed ([#10400](https://github.com/diegosouzapw/OmniRoute/pull/10400))
|
||||
- **feat(ocr):** multi-provider /v1/ocr with transformation layer (Azure Document Intelligence) ([#10283](https://github.com/diegosouzapw/OmniRoute/pull/10283))
|
||||
- **feat(providers):** declare imageToText serviceKind on major vision providers ([#10275](https://github.com/diegosouzapw/OmniRoute/pull/10275))
|
||||
- **feat(bridge):** native-vision skip guard + configurable describe output cap ([#10289](https://github.com/diegosouzapw/OmniRoute/pull/10289))
|
||||
- **feat(bridge):** normalize images to 2048px long edge before vision describe self-call ([#10287](https://github.com/diegosouzapw/OmniRoute/pull/10287))
|
||||
- **feat(sse):** restate agentrouter quota 403/400 as retryable 429 with provider-scoped error rules ([#10335](https://github.com/diegosouzapw/OmniRoute/pull/10335))
|
||||
- **feat(sse):** add i-have-adhd output style to compression catalog ([#10271](https://github.com/diegosouzapw/OmniRoute/pull/10271))
|
||||
- **feat(codex):** add OAuth fingerprint convergence modes ([#10243](https://github.com/diegosouzapw/OmniRoute/pull/10243)) — thanks @xz-dev
|
||||
- **feat(i18n):** complete Portuguese (PT-PT) translation ([#10250](https://github.com/diegosouzapw/OmniRoute/pull/10250)) — thanks @DarkEsteves
|
||||
- **feat(providers):** publish Poolside's probed Laguna Preview catalog ([#10216](https://github.com/diegosouzapw/OmniRoute/pull/10216)) — thanks @pacocartones
|
||||
- **feat(crof):** advertise reasoning effort tiers incl. max from live discovery and registry ([#10062](https://github.com/diegosouzapw/OmniRoute/pull/10062)) — thanks @excessivechaos
|
||||
- **feat(open-sse):** expose provider-level circuit breaker thresholds via env vars (#10040) ([#10046](https://github.com/diegosouzapw/OmniRoute/pull/10046)) — thanks @tiangao88
|
||||
- **feat(dashboard):** Kimi 15% first-top-up campaign — dedicated tracked link + discount-first banner copy ([#10240](https://github.com/diegosouzapw/OmniRoute/pull/10240))
|
||||
- **feat(providers):** integrate audited free-tier gateways ([#9210](https://github.com/diegosouzapw/OmniRoute/pull/9210))
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
@@ -569,63 +553,6 @@ _Living section — regenerated 2026-08-12 from all cycle commits (cycle open `e
|
||||
- **fix(i18n) — direct pushes:** restore/unescape HTML entities in UI strings, translate capability-filter messages, complete web-session guide translations and Vietnamese parity
|
||||
- **fix(providers) — direct pushes:** repair the DeepAI registry import + executor
|
||||
- **fix(deps) — direct pushes:** CVE-driven bumps (nanoid, dompurify, mermaid, js-yaml + transitive deps for 26 Dependabot alerts) and retained isolated-build runtime dependencies in the pack
|
||||
- **fix(ci):** pin Build (advisory) to a hosted runner with memory provisioning ([#10408](https://github.com/diegosouzapw/OmniRoute/pull/10408))
|
||||
- **fix(providers):** refresh the translate-path golden for the bailian Token Plan endpoint ([#10410](https://github.com/diegosouzapw/OmniRoute/pull/10410))
|
||||
- **fix(sse):** surface Qwen/Alibaba personal Token Plan quota in dashboard and preflight ([#10290](https://github.com/diegosouzapw/OmniRoute/pull/10290))
|
||||
- **fix(deps):** pin next to an exact version so a fresh upstream release cannot break installs ([#10340](https://github.com/diegosouzapw/OmniRoute/pull/10340))
|
||||
- **fix(types):** restore custom model output limit contract ([#10339](https://github.com/diegosouzapw/OmniRoute/pull/10339)) — thanks @backryun
|
||||
- **fix(sse):** stop the executor-contract guard from hot-looping the router ([#10373](https://github.com/diegosouzapw/OmniRoute/pull/10373))
|
||||
- **fix(types):** validate nonstreaming JSON contracts ([#10258](https://github.com/diegosouzapw/OmniRoute/pull/10258)) — thanks @backryun
|
||||
- **fix(types):** narrow refresh token rotation inputs ([#10257](https://github.com/diegosouzapw/OmniRoute/pull/10257)) — thanks @backryun
|
||||
- **fix(types):** normalize executor result contracts ([#10256](https://github.com/diegosouzapw/OmniRoute/pull/10256)) — thanks @backryun
|
||||
- **fix(types):** align Responses stream options ([#10255](https://github.com/diegosouzapw/OmniRoute/pull/10255)) — thanks @backryun
|
||||
- **fix(types):** narrow combo credential preflight ([#10254](https://github.com/diegosouzapw/OmniRoute/pull/10254)) — thanks @backryun
|
||||
- **fix(compression):** cap countTextTokens at 50k chars and strip base64 data URIs ([#10118](https://github.com/diegosouzapw/OmniRoute/pull/10118)) — thanks @adevwithpurpose
|
||||
- **fix(ci):** clear base-reds on release/v3.8.50 (round 4) ([#10260](https://github.com/diegosouzapw/OmniRoute/pull/10260))
|
||||
- **fix(sse):** extract perplexity-web answers from workflow_block ([#10259](https://github.com/diegosouzapw/OmniRoute/pull/10259)) — thanks @jeyhunfaslanov
|
||||
- **fix(mcp):** persist and re-attach Gemini thoughtSignature on the direct Claude<->Gemini path ([#9448](https://github.com/diegosouzapw/OmniRoute/pull/9448)) — thanks @Sam280903
|
||||
- **fix(opencode-plugin):** respect log level for lifecycle output (#8982) ([#9316](https://github.com/diegosouzapw/OmniRoute/pull/9316)) — thanks @xiaoyaner0201
|
||||
- **fix(providers):** raise default provider probe timeout from 5s to 8s ([#9283](https://github.com/diegosouzapw/OmniRoute/pull/9283)) — thanks @Sam280903
|
||||
- **fix(opencode-plugin):** stop warning when an auto combo replaces its expected /v1/models twin (#8983) ([#9042](https://github.com/diegosouzapw/OmniRoute/pull/9042)) — thanks @xiaoyaner0201
|
||||
- **fix(opencode):** force CLI User-Agent when CLI identity synthesis is enabled ([#10222](https://github.com/diegosouzapw/OmniRoute/pull/10222)) — thanks @adevwithpurpose
|
||||
- **fix(deepseek-web):** classify business auth rejection as 401 ([#10218](https://github.com/diegosouzapw/OmniRoute/pull/10218)) — thanks @Zartharas
|
||||
- **fix(combo):** make failoverBeforeRetry actually skip the same-model retry ([#10217](https://github.com/diegosouzapw/OmniRoute/pull/10217)) — thanks @hartmark
|
||||
- **fix(responses):** preserve case-insensitive combo names before Codex rewrite ([#10177](https://github.com/diegosouzapw/OmniRoute/pull/10177)) — thanks @ddarkr
|
||||
- **fix(discovery):** parse reasoning tiers nested under metadata.reasoning.supported_efforts ([#10138](https://github.com/diegosouzapw/OmniRoute/pull/10138)) — thanks @excessivechaos
|
||||
- **fix(combo):** isolate session stickiness by combo ([#10137](https://github.com/diegosouzapw/OmniRoute/pull/10137)) — thanks @hydraxman
|
||||
- **fix(combo):** default chaos SSE to comment-only for OpenAI-compatible clients ([#10128](https://github.com/diegosouzapw/OmniRoute/pull/10128)) — thanks @herjarsa
|
||||
- **fix(kimi):** normalize MFJS tool schemas ([#10079](https://github.com/diegosouzapw/OmniRoute/pull/10079)) — thanks @xz-dev
|
||||
- **fix(mcp):** move pack validation out of unit suite ([#10065](https://github.com/diegosouzapw/OmniRoute/pull/10065)) — thanks @yansigit
|
||||
- **fix(zed-hosted):** send the provider wire values cloud.zed.dev accepts ([#10051](https://github.com/diegosouzapw/OmniRoute/pull/10051)) — thanks @ARC345
|
||||
- **fix(ci):** repair and wire the two live-server E2E suites ([#10050](https://github.com/diegosouzapw/OmniRoute/pull/10050)) — thanks @ARC345
|
||||
- **fix(reasoning):** preserve and replay assistant turns ([#10045](https://github.com/diegosouzapw/OmniRoute/pull/10045)) — thanks @jackjinke
|
||||
- **fix(types):** tighten chatCore helper contracts ([#10175](https://github.com/diegosouzapw/OmniRoute/pull/10175)) — thanks @backryun
|
||||
- **fix(cli):** read the full provider catalog instead of the 6-entry fallback ([#10097](https://github.com/diegosouzapw/OmniRoute/pull/10097)) — thanks @amartinawi
|
||||
- **fix(cli):** stop swallowing non-2xx responses into benign-looking results ([#10092](https://github.com/diegosouzapw/OmniRoute/pull/10092)) — thanks @amartinawi
|
||||
- **fix(cli):** openapi endpoints/paths/validate accept the served catalog shape ([#10091](https://github.com/diegosouzapw/OmniRoute/pull/10091)) — thanks @amartinawi
|
||||
- **fix(cli):** doctor detects prebuilt better-sqlite3 binaries ([#10090](https://github.com/diegosouzapw/OmniRoute/pull/10090)) — thanks @amartinawi
|
||||
- **fix(providers):** kilo-gateway authType should be optional, not apikey ([#10086](https://github.com/diegosouzapw/OmniRoute/pull/10086)) — thanks @TengSivtean
|
||||
- **fix(cli):** strip inline comments when parsing .env values ([#10101](https://github.com/diegosouzapw/OmniRoute/pull/10101)) — thanks @amartinawi
|
||||
- **fix(logging):** document CHAT_LOG_MAX_BODY_KB, capture messageCount for Responses API bodies ([#10038](https://github.com/diegosouzapw/OmniRoute/pull/10038)) — thanks @hartmark
|
||||
- **fix(dashboard):** expose OpenAI Responses store toggle for non-Codex connections ([#10121](https://github.com/diegosouzapw/OmniRoute/pull/10121)) — thanks @hartmark
|
||||
- **fix(combo):** clear LKGP pin when its target fails, not only set it on success ([#10034](https://github.com/diegosouzapw/OmniRoute/pull/10034)) — thanks @hartmark
|
||||
- **fix(sse):** provider-response summary format bugs (dashboard Provider Response panel) ([#10037](https://github.com/diegosouzapw/OmniRoute/pull/10037)) — thanks @hartmark
|
||||
- **fix(responses-api):** tool call after reasoning collided on the same output_index ([#10025](https://github.com/diegosouzapw/OmniRoute/pull/10025)) — thanks @hartmark
|
||||
- **fix(responses-api):** explicit function-tool declaration must win over apply_patch-is-custom fallback ([#10041](https://github.com/diegosouzapw/OmniRoute/pull/10041)) — thanks @hartmark
|
||||
- **fix(kimi):** recupera limite temporario sem bloquear conta ([#10058](https://github.com/diegosouzapw/OmniRoute/pull/10058)) — thanks @bortolidiego
|
||||
- **fix(translator):** preserve Responses custom tools for OpenAI-compatible providers ([#10114](https://github.com/diegosouzapw/OmniRoute/pull/10114)) — thanks @mtb-ninja
|
||||
- **fix(providers):** xai-oauth chat→responses body + missing breaker import (#10165) ([#10170](https://github.com/diegosouzapw/OmniRoute/pull/10170)) — thanks @nordz0r
|
||||
- **fix(ollama-cloud):** map xhigh reasoning effort to max ([#10160](https://github.com/diegosouzapw/OmniRoute/pull/10160)) — thanks @Chewji9875
|
||||
- **fix(translator):** strip Codex encrypted tool-schema key for Gemini/Antigravity ([#10053](https://github.com/diegosouzapw/OmniRoute/pull/10053)) — thanks @XDayonline
|
||||
- **fix(combo):** preserve OpenCode Free oc/ prefix for connections ([#10180](https://github.com/diegosouzapw/OmniRoute/pull/10180)) — thanks @AStupidBear
|
||||
- **fix(sse):** apply free-tier filter to auto/best-free on chat path ([#10199](https://github.com/diegosouzapw/OmniRoute/pull/10199)) — thanks @ggdayup
|
||||
- **fix(providers):** default missing cache_control.ttl to 1h on the native Claude OAuth path ([#10221](https://github.com/diegosouzapw/OmniRoute/pull/10221)) — thanks @jeff-alves
|
||||
- **fix(ci):** clear base-reds on release/v3.8.50 (round 3) ([#10213](https://github.com/diegosouzapw/OmniRoute/pull/10213))
|
||||
- **fix(security):** correct XML double-unescape and non-CSPRNG nonce from CodeQL sweep ([#10154](https://github.com/diegosouzapw/OmniRoute/pull/10154))
|
||||
- **fix(docker):** eliminate npm-bundled CVEs from the published image ([#10182](https://github.com/diegosouzapw/OmniRoute/pull/10182))
|
||||
- **fix(security):** resolve open CodeQL alerts ([#10188](https://github.com/diegosouzapw/OmniRoute/pull/10188))
|
||||
- **fix(dashboard):** retarget Kimi promo CTA to the API platform aff link ([#10200](https://github.com/diegosouzapw/OmniRoute/pull/10200))
|
||||
- **fix(build):** repair broken production build, red lint gate and SWR crash ([#10198](https://github.com/diegosouzapw/OmniRoute/pull/10198))
|
||||
|
||||
### 📝 Maintenance
|
||||
|
||||
@@ -771,10 +698,6 @@ _Living section — regenerated 2026-08-12 from all cycle commits (cycle open `e
|
||||
- **deps (rollup):** dependency bumps and lockfile maintenance across the cycle — Dependabot groups and manual CVE-driven bumps ([#9081](https://github.com/diegosouzapw/OmniRoute/pull/9081), [#9082](https://github.com/diegosouzapw/OmniRoute/pull/9082), [#9427](https://github.com/diegosouzapw/OmniRoute/pull/9427), [#9458](https://github.com/diegosouzapw/OmniRoute/pull/9458), [#9459](https://github.com/diegosouzapw/OmniRoute/pull/9459), [#9461](https://github.com/diegosouzapw/OmniRoute/pull/9461), [#9462](https://github.com/diegosouzapw/OmniRoute/pull/9462), [#9472](https://github.com/diegosouzapw/OmniRoute/pull/9472))
|
||||
- **docs/chore (rollup):** documentation, refactoring and repository-hygiene upkeep across the cycle ([#8954](https://github.com/diegosouzapw/OmniRoute/pull/8954), [#8991](https://github.com/diegosouzapw/OmniRoute/pull/8991), [#9059](https://github.com/diegosouzapw/OmniRoute/pull/9059), [#9194](https://github.com/diegosouzapw/OmniRoute/pull/9194), [#9258](https://github.com/diegosouzapw/OmniRoute/pull/9258), [#9508](https://github.com/diegosouzapw/OmniRoute/pull/9508))
|
||||
- **main-branch plumbing (rollup):** work that landed on `main` between cycles and was carried into this one — the Mergify merge-queue migration and tuning (#7168, #7179, #7216, #7220, #7225), npm-publish unblock via dynamic runner + CI build reuse (#8941), CodeQL-driven e2e mock hardening (#7559), hermetic self-ref guard (#6634, #7341), coverage-baseline tightening (#7347), Dependabot alert resolutions via npm overrides (#8067, #8070), README flag/doc-link polish (#8317), and the v3.8.49 release plumbing itself (#7076)
|
||||
- **deps:** bump the development group across 1 directory with 22 updates ([#10043](https://github.com/diegosouzapw/OmniRoute/pull/10043)) — thanks @app/dependabot
|
||||
- **deps:** bump electron from 43.2.0 to 43.3.0 in /electron ([#10042](https://github.com/diegosouzapw/OmniRoute/pull/10042)) — thanks @app/dependabot
|
||||
- **maint(release):** 45 direct pushes to the release branch with no PR ref — base-red and quality-gate repairs, i18n string completion and stream/type fixes (quality ×6, i18n ×5, deps ×3, agentrouter ×3, providers ×2, release ×2, security ×2, logging ×2)
|
||||
- **maint(repo):** 29 chore/ci/test/docs commits rolled up — quality baselines, mutation registration, CI re-triggers, doc restructure and repo hygiene (#10187, #10189, #10190, #10193, #10196, #10203, #10204, #10205, #10207, #10210, #10236, #10318)
|
||||
|
||||
### 🙌 Contributors
|
||||
|
||||
@@ -783,7 +706,7 @@ Thanks to everyone whose work landed in v3.8.50:
|
||||
| Contributor | PRs / Issues |
|
||||
| --- | --- |
|
||||
| [@AbdullahFageeh](https://github.com/AbdullahFageeh) | #9087 |
|
||||
| [@adevwithpurpose](https://github.com/adevwithpurpose) | #9790, #10118, #10222 |
|
||||
| [@adevwithpurpose](https://github.com/adevwithpurpose) | #9790 |
|
||||
| [@adrianojiu](https://github.com/adrianojiu) | #8438 |
|
||||
| [@agisota](https://github.com/agisota) | #9837 |
|
||||
| [@AgnesRiber](https://github.com/AgnesRiber) | #9718, #9976 |
|
||||
@@ -791,24 +714,21 @@ Thanks to everyone whose work landed in v3.8.50:
|
||||
| [@AIB1TAL0S](https://github.com/AIB1TAL0S) | #9284 |
|
||||
| [@AlanSyue](https://github.com/AlanSyue) | direct commit / report |
|
||||
| [@alex-jordan547](https://github.com/alex-jordan547) | #9235, #9245, #9813 |
|
||||
| [@amartinawi](https://github.com/amartinawi) | #10090, #10091, #10092, #10097, #10101 |
|
||||
| [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #8888, #8889, #8890, #8891, #8892, #8893, #8894, #8895 |
|
||||
| [@AnhLead](https://github.com/AnhLead) | #9722 |
|
||||
| [@aniketshukla1](https://github.com/aniketshukla1) | #9148 |
|
||||
| [@Anjielon](https://github.com/Anjielon) | #8776 |
|
||||
| [@apoapostolov](https://github.com/apoapostolov) | #8916 |
|
||||
| [@ARC345](https://github.com/ARC345) | #9628, #10050, #10051 |
|
||||
| [@ARC345](https://github.com/ARC345) | #9628 |
|
||||
| [@artickc](https://github.com/artickc) | #8571, #8578, #8791, #8843, #8870, #8927, #8974, #9097, #9549 |
|
||||
| [@Arul-](https://github.com/Arul-) | #9761 |
|
||||
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
|
||||
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
|
||||
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10178, #10175, #10254, #10255, #10256, #10257, #10258, #10339 |
|
||||
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10178 |
|
||||
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
|
||||
| [@benzntech](https://github.com/benzntech) | #9810, #9812, #9939 |
|
||||
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
|
||||
| [@bortolidiego](https://github.com/bortolidiego) | #10058 |
|
||||
| [@branben](https://github.com/branben) | #9940 |
|
||||
| [@Chewji9875](https://github.com/Chewji9875) | #9257, #9420, #9821, #9994, #10160 |
|
||||
| [@Chewji9875](https://github.com/Chewji9875) | #9257, #9420, #9821, #9994 |
|
||||
| [@chirag127](https://github.com/chirag127) | #6674 |
|
||||
| [@chloeassistant](https://github.com/chloeassistant) | #9675, #9746 |
|
||||
| [@configurowebmax](https://github.com/configurowebmax) | #8877 |
|
||||
@@ -816,9 +736,7 @@ Thanks to everyone whose work landed in v3.8.50:
|
||||
| [@costaeder](https://github.com/costaeder) | #8626, #8629, #8630 |
|
||||
| [@csoftware-arigpt](https://github.com/csoftware-arigpt) | #3440 |
|
||||
| [@DaDecky](https://github.com/DaDecky) | direct commit / report |
|
||||
| [@DarkEsteves](https://github.com/DarkEsteves) | #10250 |
|
||||
| [@ddarkr](https://github.com/ddarkr) | #9035, #9036, #10177 |
|
||||
| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer |
|
||||
| [@ddarkr](https://github.com/ddarkr) | #9035, #9036 |
|
||||
| [@Dingding-leo](https://github.com/Dingding-leo) | #7987, #8640, #8678, #8704, #8774, #8790, #8808, #8817 |
|
||||
| [@DinonowDev](https://github.com/DinonowDev) | #8804 |
|
||||
| [@Dragost](https://github.com/Dragost) | #8339 |
|
||||
@@ -827,31 +745,26 @@ Thanks to everyone whose work landed in v3.8.50:
|
||||
| [@engmarcosjr](https://github.com/engmarcosjr) | #9993 |
|
||||
| [@epsilonode](https://github.com/epsilonode) | #8871 |
|
||||
| [@ervareza](https://github.com/ervareza) | direct commit / report |
|
||||
| [@excessivechaos](https://github.com/excessivechaos) | #10062, #10138 |
|
||||
| [@fajarhide](https://github.com/fajarhide) | #9191, #9198 |
|
||||
| [@fenix007](https://github.com/fenix007) | #9618 |
|
||||
| [@Gecky2102](https://github.com/Gecky2102) | #9280 |
|
||||
| [@ggdayup](https://github.com/ggdayup) | #10199 |
|
||||
| [@Gioxaa](https://github.com/Gioxaa) | #9162, #9171 |
|
||||
| [@HaoNgo232](https://github.com/HaoNgo232) | direct commit / report |
|
||||
| [@Hariprajwal](https://github.com/Hariprajwal) | #9922 |
|
||||
| [@hartmark](https://github.com/hartmark) | #9635, #9704, #9711, #9712, #9727, #9734, #9735, #9738, #9741, #9744, #9745, #9822, #10025, #10034, #10037, #10038, #10041, #10121, #10217 |
|
||||
| [@hartmark](https://github.com/hartmark) | #9635, #9704, #9711, #9712, #9727, #9734, #9735, #9738, #9741, #9744, #9745, #9822 |
|
||||
| [@Hdiaktoros](https://github.com/Hdiaktoros) | #8930 |
|
||||
| [@HectorBernstorff](https://github.com/HectorBernstorff) | direct commit / report |
|
||||
| [@HellFiveOsborn](https://github.com/HellFiveOsborn) | #9248 |
|
||||
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128 |
|
||||
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946 |
|
||||
| [@horacecar](https://github.com/horacecar) | #7679 |
|
||||
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929 |
|
||||
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
|
||||
| [@hydraxman](https://github.com/hydraxman) | #10137 |
|
||||
| [@Iammilansoni](https://github.com/Iammilansoni) | #9353, #9397 |
|
||||
| [@ikelvingo](https://github.com/ikelvingo) | #8591, #8872, #9053 |
|
||||
| [@infinit-X](https://github.com/infinit-X) | #9095 |
|
||||
| [@isaaclb98](https://github.com/isaaclb98) | #9730 |
|
||||
| [@jackjinke](https://github.com/jackjinke) | #9556, #9601, #10005, #10045 |
|
||||
| [@jackjinke](https://github.com/jackjinke) | #9556, #9601, #10005 |
|
||||
| [@jax-novita](https://github.com/jax-novita) | #8913 |
|
||||
| [@jeff-alves](https://github.com/jeff-alves) | #10221 |
|
||||
| [@jeyhunfaslanov](https://github.com/jeyhunfaslanov) | #10259 |
|
||||
| [@jhordanjw123](https://github.com/jhordanjw123) | #8736 |
|
||||
| [@jktan0504](https://github.com/jktan0504) | #9025 |
|
||||
| [@joachimBrindeau](https://github.com/joachimBrindeau) | #9200 |
|
||||
@@ -882,15 +795,12 @@ Thanks to everyone whose work landed in v3.8.50:
|
||||
| [@MohitRawat017](https://github.com/MohitRawat017) | #8718, #8772, #9605 |
|
||||
| [@Momen4444](https://github.com/Momen4444) | #9612 |
|
||||
| [@MrShitFox](https://github.com/MrShitFox) | #9826 |
|
||||
| [@mtb-ninja](https://github.com/mtb-ninja) | #10114 |
|
||||
| [@MumuTW](https://github.com/MumuTW) | #8839 |
|
||||
| [@mvanhorn](https://github.com/mvanhorn) | #9542 |
|
||||
| [@Mynacol](https://github.com/Mynacol) | #9733 |
|
||||
| [@nguyenha935](https://github.com/nguyenha935) | #9044, #9215 |
|
||||
| [@nordz0r](https://github.com/nordz0r) | #10170 |
|
||||
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
|
||||
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818 |
|
||||
| [@pacocartones](https://github.com/pacocartones) | #10216 |
|
||||
| [@PixmaNts](https://github.com/PixmaNts) | #9432 |
|
||||
| [@pizzav-xyz](https://github.com/pizzav-xyz) | #9077 |
|
||||
| [@Poid-ZA](https://github.com/Poid-ZA) | #9467 |
|
||||
@@ -907,7 +817,7 @@ Thanks to everyone whose work landed in v3.8.50:
|
||||
| [@ryanngit](https://github.com/ryanngit) | direct commit / report |
|
||||
| [@sadSanta-07](https://github.com/sadSanta-07) | #9938 |
|
||||
| [@SalyyS1](https://github.com/SalyyS1) | direct commit / report |
|
||||
| [@Sam280903](https://github.com/Sam280903) | #9274, #9278, #9281, #9283, #9448 |
|
||||
| [@Sam280903](https://github.com/Sam280903) | #9274, #9278, #9281 |
|
||||
| [@seakleangnhak](https://github.com/seakleangnhak) | direct commit / report |
|
||||
| [@seanford](https://github.com/seanford) | #8523 |
|
||||
| [@SemonCat](https://github.com/SemonCat) | direct commit / report |
|
||||
@@ -921,28 +831,27 @@ Thanks to everyone whose work landed in v3.8.50:
|
||||
| [@tald26](https://github.com/tald26) | #9959 |
|
||||
| [@taltas](https://github.com/taltas) | direct commit / report |
|
||||
| [@TechNickAI](https://github.com/TechNickAI) | #9251 |
|
||||
| [@TengSivtean](https://github.com/TengSivtean) | #10000, #10002, #10086 |
|
||||
| [@TengSivtean](https://github.com/TengSivtean) | #10000, #10002 |
|
||||
| [@TheFrenchGhosty](https://github.com/TheFrenchGhosty) | #9326 |
|
||||
| [@tiangao88](https://github.com/tiangao88) | #10046 |
|
||||
| [@tuxmonteiro](https://github.com/tuxmonteiro) | #9065 |
|
||||
| [@vinogradovnet](https://github.com/vinogradovnet) | #9581 |
|
||||
| [@VXNCXNX](https://github.com/VXNCXNX) | #9111, #9783 |
|
||||
| [@wgordon17](https://github.com/wgordon17) | #8909, #9233, #9441, #9619 |
|
||||
| [@Witroch4](https://github.com/Witroch4) | #8713 |
|
||||
| [@witt3rd](https://github.com/witt3rd) | #9962, #9963 |
|
||||
| [@XDayonline](https://github.com/XDayonline) | #10053 |
|
||||
| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8757, #8869, #8876, #8883, #8906, #8931, #9021, #9027, #9452, #9042, #9316 |
|
||||
| [@xz-dev](https://github.com/xz-dev) | #8908, #9199, #9205, #9262, #9290, #9313, #9555, #9569, #9629, #9788, #9983, #10079, #10243 |
|
||||
| [@yansigit](https://github.com/yansigit) | #9834, #9911, #9917, #9921, #10065 |
|
||||
| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8757, #8869, #8876, #8883, #8906, #8931, #9021, #9027, #9452 |
|
||||
| [@xz-dev](https://github.com/xz-dev) | #8908, #9199, #9205, #9262, #9290, #9313, #9555, #9569, #9629, #9788, #9983 |
|
||||
| [@yansigit](https://github.com/yansigit) | #9834, #9911, #9917, #9921 |
|
||||
| [@yidecode](https://github.com/yidecode) | direct commit / report |
|
||||
| [@yulinlina](https://github.com/yulinlina) | #10013 |
|
||||
| [@yutuknown](https://github.com/yutuknown) | #8999 |
|
||||
| [@zabrodschiipavel-sketch](https://github.com/zabrodschiipavel-sketch) | #9312 |
|
||||
| [@Zartharas](https://github.com/Zartharas) | #9161, #9164, #9181, #9182, #9184, #9185, #9186, #9189, #9294, #9825, #9833, #9936, #9965, #9992, #10218 |
|
||||
| [@Zartharas](https://github.com/Zartharas) | #9161, #9164, #9181, #9182, #9184, #9185, #9186, #9189, #9294, #9825, #9833, #9936, #9965, #9992 |
|
||||
| [@Zenlyte](https://github.com/Zenlyte) | #9005 |
|
||||
| [@zhiru](https://github.com/zhiru) | #9099, #9101 |
|
||||
| [@ziuus](https://github.com/ziuus) | #8912 |
|
||||
| [@zuckdorsey](https://github.com/zuckdorsey) | #9723 |
|
||||
| [@diegosouzapw](https://github.com/diegosouzapw) | maintainer |
|
||||
|
||||
---
|
||||
|
||||
|
||||
22
Dockerfile
@@ -8,8 +8,8 @@ WORKDIR /app
|
||||
# that already have a fix published in trixie. CVEs without an upstream fix yet
|
||||
# (local-only TOCTOU, etc.) remain until the distro patches them and the image
|
||||
# is rebuilt; none are reachable from the proxy's request surface at runtime.
|
||||
RUN --mount=type=cache,id=s/92ca8a61-c1ba-421f-a389-d48ac7258c2d-apt-cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,id=s/92ca8a61-c1ba-421f-a389-d48ac7258c2d-apt-lists,target=/var/lib/apt/lists,sharing=locked \
|
||||
RUN --mount=type=cache,id=apt-cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,id=apt-lists,target=/var/lib/apt/lists,sharing=locked \
|
||||
apt-get update \
|
||||
&& apt-get upgrade -y \
|
||||
&& apt-get install -y --no-install-recommends libsecret-1-0 ca-certificates \
|
||||
@@ -61,8 +61,8 @@ FROM base AS builder
|
||||
|
||||
# Build tools for native module compilation
|
||||
# apt-get update needed here because base's rm -rf clears the shared cache
|
||||
RUN --mount=type=cache,id=s/92ca8a61-c1ba-421f-a389-d48ac7258c2d-apt-cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,id=s/92ca8a61-c1ba-421f-a389-d48ac7258c2d-apt-lists,target=/var/lib/apt/lists,sharing=locked \
|
||||
RUN --mount=type=cache,id=apt-cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,id=apt-lists,target=/var/lib/apt/lists,sharing=locked \
|
||||
apt-get update \
|
||||
&& apt-get install -y --no-install-recommends python3 make g++ \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
@@ -108,7 +108,7 @@ RUN test -f package-lock.json \
|
||||
# in production (TlsClientUnavailableError, #7802). Run it explicitly here so
|
||||
# a broken/rate-limited fetch fails the BUILD loudly instead of shipping a
|
||||
# broken image.
|
||||
RUN --mount=type=cache,id=s/92ca8a61-c1ba-421f-a389-d48ac7258c2d-npm-cache,target=/root/.npm \
|
||||
RUN --mount=type=cache,id=npm-cache,target=/root/.npm \
|
||||
npm ci --include=optional --no-audit --no-fund --legacy-peer-deps --ignore-scripts \
|
||||
&& (cd node_modules/better-sqlite3 \
|
||||
&& node /usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js rebuild) \
|
||||
@@ -158,7 +158,7 @@ ARG OMNIROUTE_BUILD_MEMORY_MB=4096
|
||||
ENV NODE_OPTIONS="--max-old-space-size=${OMNIROUTE_BUILD_MEMORY_MB}"
|
||||
|
||||
COPY . ./
|
||||
RUN --mount=type=cache,id=s/92ca8a61-c1ba-421f-a389-d48ac7258c2d-next-cache,target=/app/.build/next/cache \
|
||||
RUN --mount=type=cache,id=next-cache,target=/app/.build/next/cache \
|
||||
mkdir -p /app/data \
|
||||
&& npm run build \
|
||||
&& node --input-type=module -e "import { createRequire } from 'node:module'; import { pathToFileURL } from 'node:url'; const standaloneRoot = '/app/.build/next/standalone/node_modules/'; const require = createRequire('/app/.build/next/standalone/package.json'); for (const pkg of ['@atjsh/llmlingua-2', '@huggingface/transformers', '@tensorflow/tfjs', 'js-tiktoken']) { const resolved = require.resolve(pkg); if (!resolved.startsWith(standaloneRoot)) throw new Error(pkg + ' resolved outside standalone: ' + resolved); await import(pathToFileURL(resolved).href); } const onnxRuntime = require.resolve('onnxruntime-node'); if (!onnxRuntime.startsWith(standaloneRoot)) throw new Error('onnxruntime-node resolved outside standalone: ' + onnxRuntime); await import(pathToFileURL(onnxRuntime).href);"
|
||||
@@ -262,8 +262,8 @@ COPY --from=builder /app/node_modules/playwright ./node_modules/playwright
|
||||
# browsers land under /home/node which persists across image layers and is
|
||||
# accessible to the non-root runtime user.
|
||||
ENV PLAYWRIGHT_BROWSERS_PATH=/home/node/.cache/ms-playwright
|
||||
RUN --mount=type=cache,id=s/92ca8a61-c1ba-421f-a389-d48ac7258c2d-apt-cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,id=s/92ca8a61-c1ba-421f-a389-d48ac7258c2d-apt-lists,target=/var/lib/apt/lists,sharing=locked \
|
||||
RUN --mount=type=cache,id=apt-cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,id=apt-lists,target=/var/lib/apt/lists,sharing=locked \
|
||||
apt-get update \
|
||||
&& node node_modules/playwright/cli.js install chromium --with-deps \
|
||||
&& chown -R node:node /home/node/.cache \
|
||||
@@ -284,15 +284,15 @@ COPY --from=builder /app/node_modules/playwright-core ./node_modules/playwright-
|
||||
COPY --from=builder /app/node_modules/playwright ./node_modules/playwright
|
||||
|
||||
# Install system dependencies required by openclaw (git+ssh references).
|
||||
RUN --mount=type=cache,id=s/92ca8a61-c1ba-421f-a389-d48ac7258c2d-apt-cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,id=s/92ca8a61-c1ba-421f-a389-d48ac7258c2d-apt-lists,target=/var/lib/apt/lists,sharing=locked \
|
||||
RUN --mount=type=cache,id=apt-cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,id=apt-lists,target=/var/lib/apt/lists,sharing=locked \
|
||||
apt-get update \
|
||||
&& apt-get install -y --no-install-recommends git ca-certificates docker.io docker-compose \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& git config --system url."https://github.com/".insteadOf "ssh://git@github.com/"
|
||||
|
||||
# Install CLI tools globally. Separate layer from apt for better cache reuse.
|
||||
RUN --mount=type=cache,id=s/92ca8a61-c1ba-421f-a389-d48ac7258c2d-npm-cache,target=/root/.npm \
|
||||
RUN --mount=type=cache,id=npm-cache,target=/root/.npm \
|
||||
npm install -g --no-audit --no-fund @openai/codex @anthropic-ai/claude-code droid openclaw@latest
|
||||
|
||||
USER node
|
||||
|
||||
75
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 → 340 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. 340 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 → 339 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. 339 AI providers · 90+ free tiers · ~1.51B free tokens/mo · 19 routing strategies · $0 to start."/>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -63,10 +63,10 @@
|
||||
|
||||
| | v3.8.49 | **v3.8.50** | `v3.8.51+` |
|
||||
| ------------------------- | :-----: | :---------: | :---------: |
|
||||
| 🌐 Providers | 290 | **340** | more queued |
|
||||
| 🧠 Documented models | 1185 | **1202** | — |
|
||||
| 🌐 Providers | 291 | **339** | more queued |
|
||||
| 🧠 Documented models | 500+ | **1200+** | — |
|
||||
| 🖼️ Modality Bridge | — | 🆕 vision | video |
|
||||
| 📡 Radar free catalog | — | 🆕 opt-in | — |
|
||||
| 📡 Radar free catalog | — | — | 🔭 next |
|
||||
| ⚖️ Quota-aware scheduling | — | — | 🔭 next |
|
||||
| 📊 Quota telemetry | — | — | 🔭 next |
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
<tr>
|
||||
<td align="right"><b>⚙️ Features</b></td>
|
||||
<td align="center"><a href="#-combos--the-flagship">🎯 Combos</a></td>
|
||||
<td align="center"><a href="#-340-ai-providers--90-free">🌐 Providers</a></td>
|
||||
<td align="center"><a href="#-339-ai-providers--90-free">🌐 Providers</a></td>
|
||||
<td align="center"><a href="#-full-cli--a2a--mcp">🔌 CLI & MCP</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -210,7 +210,7 @@ curl http://localhost:20128/v1/chat/completions \
|
||||
|
||||
</div>
|
||||
|
||||
<img src="./docs/diagrams/promise-pillars.svg" width="100%" alt="The Promise — One endpoint. 340 providers. Never stop building — OmniRoute picks the cheapest one that works. Six pillars: Never hit limits (auto-fallback across 340 providers in milliseconds, zero downtime) · Save up to 95% tokens (RTK + Caveman stacked compression cuts 15–95%, ~89% avg on tool-heavy sessions) · $0 to start (90+ free tiers, 56 free forever — no card needed) · Every tool works (33 coding agents through one config) · One endpoint (OpenAI ↔ Claude ↔ Gemini ↔ Responses API at /v1) · Production-grade (circuit breakers, TLS stealth, MCP 109 tools, A2A, memory, guardrails, evals — 25,000+ tests)."/>
|
||||
<img src="./docs/diagrams/promise-pillars.svg" width="100%" alt="The Promise — One endpoint. 339 providers. Never stop building — OmniRoute picks the cheapest one that works. Six pillars: Never hit limits (auto-fallback across 339 providers in milliseconds, zero downtime) · Save up to 95% tokens (RTK + Caveman stacked compression cuts 15–95%, ~89% avg on tool-heavy sessions) · $0 to start (90+ free tiers, 40+ free forever — no card needed) · Every tool works (33 coding agents through one config) · One endpoint (OpenAI ↔ Claude ↔ Gemini ↔ Responses API at /v1) · Production-grade (circuit breakers, TLS stealth, MCP 105 tools, A2A, memory, guardrails, evals — 25,000+ tests)."/>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
@@ -449,7 +449,7 @@ All **19** strategies — mix & match per combo step:
|
||||
|
||||
### 🧱 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 3× / API-key 5× / 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 +461,7 @@ All **19** strategies — mix & match per combo step:
|
||||
|
||||
</div>
|
||||
|
||||
<img src="./docs/diagrams/comparison-table.svg" width="100%" alt="What sets OmniRoute apart — comparison table vs 9router, OpenRouter, CLIProxyAPI and LiteLLM across 13 capabilities. OmniRoute: 340 providers, 90+ free providers built-in, 19 routing strategies, 12-engine token compression, built-in MCP server with 109 tools, A2A agent protocol, persistent memory, guardrails, cloud agents, TLS fingerprint stealth, Desktop/Termux/PWA, 43 i18n UI locales, 100% MIT self-hosted. OmniRoute is the only one with the full set; competitors show a mix of checks, partials and crosses. Verified from each project's docs."/>
|
||||
<img src="./docs/diagrams/comparison-table.svg" width="100%" alt="What sets OmniRoute apart — comparison table vs 9router, OpenRouter, CLIProxyAPI and LiteLLM across 13 capabilities. OmniRoute: 339 providers, 90+ free providers built-in, 19 routing strategies, 12-engine token compression, built-in MCP server with 105 tools, A2A agent protocol, persistent memory, guardrails, cloud agents, TLS fingerprint stealth, Desktop/Termux/PWA, 43 i18n UI locales, 100% MIT self-hosted. OmniRoute is the only one with the full set; competitors show a mix of checks, partials and crosses. Verified from each project's docs."/>
|
||||
|
||||
<sub>📊 Full methodology & per-feature detail vs 9router, OpenRouter, CLIProxyAPI & LiteLLM → [`docs/comparison/OMNIROUTE_VS_ALTERNATIVES.md`](docs/comparison/OMNIROUTE_VS_ALTERNATIVES.md)</sub>
|
||||
|
||||
@@ -513,25 +513,6 @@ Pix copia-e-cola:
|
||||
|
||||
<br/>
|
||||
|
||||
## 📡 OmniRoute Radar
|
||||
|
||||
The main free-tier headline remains **~1.53B tokens/month** from the documented,
|
||||
pool-deduplicated catalog above. Temporary provider signup credits can separately lift the first
|
||||
month to **~2.15B**. Radar is an optional, signed catalog overlay for people who want fresher
|
||||
free-model availability between OmniRoute releases; the community catalog and every existing free
|
||||
feature remain free.
|
||||
|
||||
Supporters can receive the live catalog and additional provider opportunities. Its separate,
|
||||
mutable ceiling is **approximately 3B tokens/month at most**, depending on provider availability.
|
||||
That ceiling is not a guarantee: providers can change quotas, eligibility, models, or regions at
|
||||
any time.
|
||||
|
||||
Radar is opt-in and GET-only. The OmniRoute client does not upload prompts, traffic, provider
|
||||
configuration, usage telemetry, or local announcement-dismiss state. Learn about eligibility and
|
||||
the current catalog at **[radar.omniroute.online/planos](https://radar.omniroute.online/planos)**.
|
||||
|
||||
<br/>
|
||||
|
||||
<div align="center">
|
||||
|
||||
## ✨ What's New
|
||||
@@ -557,7 +538,7 @@ 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, Freepik, Adobe Firefly, Microsoft Designer, Google Imagen, Segmind, EdgeTTS. → [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 **340-provider catalog**. → [Providers](docs/reference/PROVIDER_REFERENCE.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 **339-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)
|
||||
|
||||
@@ -618,11 +599,11 @@ the current catalog at **[radar.omniroute.online/planos](https://radar.omniroute
|
||||
|
||||
<div align="center">
|
||||
|
||||
## 🌐 340 AI Providers — 90+ Free
|
||||
## 🌐 339 AI Providers — 90+ Free
|
||||
|
||||
</div>
|
||||
|
||||
> The most complete catalog of any open-source router: **340 providers**, **90+ with a free tier**, **56 free forever**.
|
||||
> The most complete catalog of any open-source router: **339 providers**, **90+ with a free tier**, **40+ free forever**.
|
||||
|
||||
<div align="center">
|
||||
|
||||
@@ -702,7 +683,6 @@ the current catalog at **[radar.omniroute.online/planos](https://radar.omniroute
|
||||
<tr><td align="left" nowrap>📱 <b>Android (Termux)</b></td><td align="left" nowrap><code>pkg install nodejs && npx -y omniroute</code></td><td align="left">Runs <b>on your phone</b>, 24/7, no root</td></tr>
|
||||
<tr><td align="left" nowrap>📲 <b>PWA</b></td><td align="left" nowrap>"Add to Home Screen"</td><td align="left">Fullscreen, offline, installable from browser</td></tr>
|
||||
<tr><td align="left" nowrap>🧩 <b>OpenCode plugin</b></td><td align="left" nowrap><code>@omniroute/opencode-provider</code></td><td align="left">Native OpenCode integration</td></tr>
|
||||
<tr><td align="left" nowrap>🤖 <b>VS Code Copilot Chat</b></td><td align="left" nowrap>install <b>OmniCopilot</b> extension</td><td align="left">Every OmniRoute model in the native Copilot Chat picker — stable & Insiders</td></tr>
|
||||
<tr><td align="left" nowrap>🛠️ <b>From source</b></td><td align="left" nowrap><code>npm install && npm run dev</code></td><td align="left">Hack on it, contribute</td></tr>
|
||||
</table>
|
||||
|
||||
@@ -712,33 +692,6 @@ the current catalog at **[radar.omniroute.online/planos](https://radar.omniroute
|
||||
|
||||
<div align="center">
|
||||
|
||||
### 🧩 New: OmniRoute inside VS Code's native Copilot Chat
|
||||
|
||||
</div>
|
||||
|
||||
> No new sidebar, no new chat UI — every model OmniRoute serves shows up right in the
|
||||
> **Copilot Chat model picker you already use**. Since VS Code 1.122, provider models work
|
||||
> without a GitHub sign-in or a Copilot subscription — agent mode, tool calling and vision, for
|
||||
> free.
|
||||
|
||||
Install the **[OmniCopilot](https://github.com/diegosouzapw/OmniCopilot)** extension, point it
|
||||
at your OmniRoute server (defaults to `localhost:20128`), then open Copilot Chat → model picker
|
||||
→ **Manage Models…** → **OmniRoute**.
|
||||
|
||||
<table>
|
||||
<tr><th align="left">Store</th><th align="left">Link</th><th align="left">Works with</th></tr>
|
||||
<tr><td align="left" nowrap>🧩 <b>VS Code Marketplace</b></td><td align="left"><a href="https://marketplace.visualstudio.com/items?itemName=diegosouzapw.omnicopilot">Install →</a></td><td align="left">VS Code — stable & Insiders</td></tr>
|
||||
<tr><td align="left" nowrap>🔓 <b>Open VSX Registry</b></td><td align="left"><a href="https://open-vsx.org/extension/diegosouzapw/omnicopilot">Install →</a></td><td align="left">Cursor, Windsurf, VSCodium, Theia, code-server, Gitpod, Antigravity, Kiro…</td></tr>
|
||||
</table>
|
||||
|
||||
From inside the editor: open the **Extensions** view, search **"OmniRoute"**, click **Install**
|
||||
— works the same way on both stores. Source, issues and the publishing runbook live at
|
||||
[diegosouzapw/OmniCopilot](https://github.com/diegosouzapw/OmniCopilot).
|
||||
|
||||
<br/>
|
||||
|
||||
<div align="center">
|
||||
|
||||
## 🔒 Private & Local-First
|
||||
|
||||
</div>
|
||||
@@ -795,7 +748,7 @@ 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>109 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>105 tools</b>, 31 scopes, 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>
|
||||
@@ -1108,7 +1061,7 @@ same process on one port, so there is no separate CLI-only package today.
|
||||
<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) — 117 domain modules, 148 migrations</td></tr>
|
||||
<tr><td nowrap><b>Database</b></td><td>better-sqlite3 (SQLite, WAL journaling) + LowDB (JSON legacy) — 95 domain modules, 145 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>
|
||||
@@ -1182,7 +1135,7 @@ same process on one port, so there is no separate CLI-only package today.
|
||||
<tr><th align="left">Document</th><th align="left">Description</th></tr>
|
||||
<tr><td nowrap><b><a href="docs/reference/API_REFERENCE.md">API Reference</a></b></td><td>All endpoints with examples</td></tr>
|
||||
<tr><td nowrap><b><a href="docs/openapi.yaml">OpenAPI Spec</a></b></td><td>OpenAPI 3.0 specification</td></tr>
|
||||
<tr><td nowrap><b><a href="open-sse/mcp-server/README.md">MCP Server</a></b></td><td>109 MCP tools, IDE configs, Python/TS/Go clients</td></tr>
|
||||
<tr><td nowrap><b><a href="open-sse/mcp-server/README.md">MCP Server</a></b></td><td>105 MCP tools, IDE configs, Python/TS/Go clients</td></tr>
|
||||
<tr><td nowrap><b><a href="docs/frameworks/MCP-SERVER.md">MCP Server Guide</a></b></td><td>MCP installation, transports, and tool reference</td></tr>
|
||||
<tr><td nowrap><b><a href="src/lib/a2a/README.md">A2A Server</a></b></td><td>JSON-RPC 2.0 protocol, skills, streaming, task mgmt</td></tr>
|
||||
<tr><td nowrap><b><a href="docs/frameworks/A2A-SERVER.md">A2A Server Guide</a></b></td><td>A2A agent card, tasks, skills, and streaming</td></tr>
|
||||
|
||||
@@ -5,7 +5,6 @@ import fs from "node:fs";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { resolveDataDir } from "../data-dir.mjs";
|
||||
import { registerContexts } from "./contexts.mjs";
|
||||
import { guardHostConfigTarget } from "../utils/config-home-guard.mjs";
|
||||
|
||||
function ensureBackup(configPath) {
|
||||
if (!fs.existsSync(configPath)) return;
|
||||
@@ -88,13 +87,6 @@ async function runConfigSetCommand(toolId, opts = {}) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const guard = await guardHostConfigTarget(result.configPath, {
|
||||
toolLabel: toolId,
|
||||
hostCommand: `omniroute config set ${toolId}`,
|
||||
allowContainerWrite: Boolean(opts.allowContainerWrite ?? opts["allow-container-write"]),
|
||||
});
|
||||
if (guard !== 0) return guard;
|
||||
|
||||
const nonInteractive = opts.nonInteractive || opts.yes;
|
||||
|
||||
if (!nonInteractive) {
|
||||
@@ -279,10 +271,6 @@ export function registerConfig(program) {
|
||||
.option("--model <model>", "Model identifier (where applicable)")
|
||||
.option("--non-interactive", "Do not prompt for confirmation")
|
||||
.option("--yes", "Skip confirmation prompt")
|
||||
.option(
|
||||
"--allow-container-write",
|
||||
"Write the config even when OmniRoute runs in a container and the target is not mounted from the host"
|
||||
)
|
||||
.action(async (tool, opts, cmd) => {
|
||||
const globalOpts = cmd.parent.optsWithGlobals();
|
||||
const exitCode = await runConfigSetCommand(tool, {
|
||||
@@ -318,10 +306,6 @@ export function registerConfig(program) {
|
||||
.option("--model <model>", "Model identifier")
|
||||
.option("--non-interactive", "Do not prompt for confirmation")
|
||||
.option("--yes", "Skip confirmation prompt")
|
||||
.option(
|
||||
"--allow-container-write",
|
||||
"Write the config even when OmniRoute runs in a container and the target is not mounted from the host"
|
||||
)
|
||||
.action(async (opts, cmd) => {
|
||||
const globalOpts = cmd.parent.optsWithGlobals();
|
||||
const exitCode = await runConfigSetCommand("opencode", {
|
||||
|
||||
@@ -4,7 +4,6 @@ import { existsSync, mkdirSync, writeFileSync, copyFileSync } from "node:fs";
|
||||
import { apiFetch } from "../api.mjs";
|
||||
import { createPrompt, printSuccess, printError, printInfo, printHeading } from "../io.mjs";
|
||||
import { t } from "../i18n.mjs";
|
||||
import { guardHostConfigTarget } from "../utils/config-home-guard.mjs";
|
||||
|
||||
/**
|
||||
* `omniroute configure <cli>` — interactive provider+model picker that writes a
|
||||
@@ -76,12 +75,6 @@ function buildCodexProfile(modelId, ctx) {
|
||||
|
||||
async function configureCodex(modelId, ctxWindow, opts) {
|
||||
const codexHome = opts.codexHome || path.join(os.homedir(), ".codex");
|
||||
const guard = await guardHostConfigTarget(codexHome, {
|
||||
toolLabel: "Codex",
|
||||
hostCommand: "omniroute configure codex",
|
||||
allowContainerWrite: Boolean(opts.allowContainerWrite ?? opts["allow-container-write"]),
|
||||
});
|
||||
if (guard !== 0) return guard;
|
||||
if (!existsSync(codexHome)) mkdirSync(codexHome, { recursive: true });
|
||||
const profile = opts.name || profileNameFromModel(modelId);
|
||||
const filePath = path.join(codexHome, `${profile}.config.toml`);
|
||||
@@ -93,7 +86,6 @@ async function configureCodex(modelId, ctxWindow, opts) {
|
||||
printInfo(`Use it: codex --profile ${profile}`);
|
||||
printInfo("Prereq: ~/.codex/config.toml must define the [model_providers.omniroute] block");
|
||||
printInfo(" (run the Codex setup once — see docs/guides/CODEX-CLI-CONFIGURATION.md).");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export async function runConfigureCommand(cli, opts = {}, cmd) {
|
||||
@@ -138,9 +130,7 @@ export async function runConfigureCommand(cli, opts = {}, cmd) {
|
||||
}
|
||||
const inProvider = ids.filter((id) => providerList.includes(providerOf(byId(models, id))));
|
||||
const candidates = inProvider.length ? inProvider : ids;
|
||||
printInfo(
|
||||
`Models: ${candidates.slice(0, 40).join(", ")}${candidates.length > 40 ? " …" : ""}`
|
||||
);
|
||||
printInfo(`Models: ${candidates.slice(0, 40).join(", ")}${candidates.length > 40 ? " …" : ""}`);
|
||||
chosenId = await prompt.ask("Model id");
|
||||
} finally {
|
||||
prompt.close();
|
||||
@@ -159,7 +149,7 @@ export async function runConfigureCommand(cli, opts = {}, cmd) {
|
||||
const ctxWindow = contextWindowOf(entry);
|
||||
|
||||
if (target === "codex") {
|
||||
return await configureCodex(chosenId, ctxWindow, opts);
|
||||
await configureCodex(chosenId, ctxWindow, opts);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -183,10 +173,6 @@ export function registerConfigure(program) {
|
||||
.option("--model <id>", "Model id (skips the interactive model prompt)")
|
||||
.option("--name <name>", "Profile name to write (default: derived from model)")
|
||||
.option("--codex-home <dir>", "Codex home dir (default: ~/.codex)")
|
||||
.option(
|
||||
"--allow-container-write",
|
||||
"Write the config even when OmniRoute runs in a container and the target is not mounted from the host"
|
||||
)
|
||||
.action(async (cli, opts, cmd) => {
|
||||
const code = await runConfigureCommand(cli, opts, cmd);
|
||||
if (code !== 0) process.exit(code);
|
||||
|
||||
@@ -1,166 +0,0 @@
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
import { t } from "../i18n.mjs";
|
||||
import { resolveDataDir } from "../data-dir.mjs";
|
||||
import {
|
||||
EXIT_CODES,
|
||||
emit,
|
||||
exitWith,
|
||||
printError,
|
||||
printInfo,
|
||||
printSuccess,
|
||||
printWarning,
|
||||
} from "../output.mjs";
|
||||
import { findPack } from "../../../scripts/packs/optionalPackManifest.mjs";
|
||||
import {
|
||||
findPackIndexFile,
|
||||
installPack,
|
||||
listPackStates,
|
||||
packState,
|
||||
packsRoot,
|
||||
readPackIndex,
|
||||
removePack,
|
||||
} from "../../../scripts/packs/optionalPackInstaller.mjs";
|
||||
|
||||
const CLI_DIR = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
|
||||
|
||||
/**
|
||||
* Locate + parse the bundle-shipped `optional-packs.index.json`.
|
||||
* Search order: explicit --source dir, then walking up from the CLI module
|
||||
* (bundle installs keep the index at the bundle root), then cwd.
|
||||
*/
|
||||
function loadIndex(sourceDir) {
|
||||
const indexFile = findPackIndexFile([sourceDir, CLI_DIR, process.cwd()]);
|
||||
if (!indexFile) return { indexFile: null, index: null };
|
||||
return { indexFile, index: readPackIndex(indexFile) };
|
||||
}
|
||||
|
||||
function stateRow(state, dataDir) {
|
||||
return {
|
||||
pack: state.name,
|
||||
packVersion: state.packVersion,
|
||||
installed: state.installed ? "yes" : "no",
|
||||
verified: state.verified === null ? "-" : state.verified ? "ok" : "FAILED",
|
||||
members: state.members.length,
|
||||
installDir: path.join(packsRoot(dataDir), state.name),
|
||||
errors: state.errors ?? [],
|
||||
};
|
||||
}
|
||||
|
||||
const STATE_SCHEMA = [
|
||||
{ key: "pack", header: "pack" },
|
||||
{ key: "packVersion", header: "packVersion" },
|
||||
{ key: "installed", header: "installed" },
|
||||
{ key: "verified", header: "verified" },
|
||||
{ key: "members", header: "members" },
|
||||
];
|
||||
|
||||
async function run(action) {
|
||||
try {
|
||||
await action();
|
||||
} catch (err) {
|
||||
exitWith(EXIT_CODES.ERROR, err instanceof Error ? err.message : String(err));
|
||||
}
|
||||
}
|
||||
|
||||
export function registerPacks(program) {
|
||||
const packs = program.command("packs").description(t("packs.description"));
|
||||
|
||||
packs
|
||||
.command("list")
|
||||
.description(t("packs.listDescription"))
|
||||
.option("--source <dir>", t("packs.sourceOpt"))
|
||||
.action(async (opts) => {
|
||||
await run(async () => {
|
||||
const dataDir = resolveDataDir();
|
||||
const { index } = loadIndex(opts.source);
|
||||
emit(
|
||||
(await listPackStates({ dataDir, index })).map((s) => stateRow(s, dataDir)),
|
||||
opts,
|
||||
STATE_SCHEMA
|
||||
);
|
||||
if (!index) printWarning(t("packs.warnNoIndex"));
|
||||
});
|
||||
});
|
||||
|
||||
packs
|
||||
.command("install <name>")
|
||||
.description(t("packs.installDescription"))
|
||||
.option("--source <dir>", t("packs.sourceOpt"))
|
||||
.action(async (name, opts) => {
|
||||
await run(async () => {
|
||||
if (!findPack(name)) exitWith(EXIT_CODES.INVALID_ARG, t("packs.errUnknown", { name }));
|
||||
const { indexFile, index } = loadIndex(opts.source);
|
||||
if (!index) exitWith(EXIT_CODES.ERROR, t("packs.errNoIndex"));
|
||||
const dataDir = resolveDataDir();
|
||||
// The payload (tarball or extracted pack dir) lives next to the index
|
||||
// unless the caller pointed elsewhere via --source.
|
||||
await installPack(name, {
|
||||
dataDir,
|
||||
index,
|
||||
sourceDir: opts.source || path.dirname(indexFile),
|
||||
log: (msg) => printInfo(msg.replace(/^\[optional-packs\]\s*/, "")),
|
||||
});
|
||||
const installDir = path.join(packsRoot(dataDir), name);
|
||||
printSuccess(t("packs.installed", { name, dir: installDir }));
|
||||
printInfo(t("packs.restartHint"));
|
||||
emit({ pack: name, installed: "yes", verified: "ok", installDir }, opts, STATE_SCHEMA);
|
||||
});
|
||||
});
|
||||
|
||||
packs
|
||||
.command("verify [name]")
|
||||
.description(t("packs.verifyDescription"))
|
||||
.option("--source <dir>", t("packs.sourceOpt"))
|
||||
.action(async (name, opts) => {
|
||||
await run(async () => {
|
||||
if (name && !findPack(name))
|
||||
exitWith(EXIT_CODES.INVALID_ARG, t("packs.errUnknown", { name }));
|
||||
const { index } = loadIndex(opts.source);
|
||||
if (!index) exitWith(EXIT_CODES.ERROR, t("packs.errNoIndex"));
|
||||
const dataDir = resolveDataDir();
|
||||
const states = name
|
||||
? [await packState(name, { dataDir, index })]
|
||||
: await listPackStates({ dataDir, index });
|
||||
emit(
|
||||
states.map((s) => stateRow(s, dataDir)),
|
||||
opts,
|
||||
STATE_SCHEMA
|
||||
);
|
||||
const broken = states.filter((s) => s.installed && s.verified !== true);
|
||||
if (broken.length > 0) {
|
||||
for (const state of broken) {
|
||||
for (const error of state.errors ?? []) printError(`${state.name}: ${error}`);
|
||||
}
|
||||
exitWith(EXIT_CODES.ERROR, t("packs.verifyFailed", { count: broken.length }));
|
||||
}
|
||||
if (!states.some((s) => s.installed)) {
|
||||
printInfo(t("packs.noneInstalled"));
|
||||
return;
|
||||
}
|
||||
printSuccess(t("packs.verifyOk"));
|
||||
});
|
||||
});
|
||||
|
||||
packs
|
||||
.command("remove <name>")
|
||||
.description(t("packs.removeDescription"))
|
||||
.action(async (name, opts) => {
|
||||
await run(async () => {
|
||||
if (!findPack(name)) exitWith(EXIT_CODES.INVALID_ARG, t("packs.errUnknown", { name }));
|
||||
const dataDir = resolveDataDir();
|
||||
const removed = removePack(name, {
|
||||
dataDir,
|
||||
log: (msg) => printInfo(msg.replace(/^\[optional-packs\]\s*/, "")),
|
||||
});
|
||||
if (removed) {
|
||||
printSuccess(t("packs.removed", { name }));
|
||||
printInfo(t("packs.restartHint"));
|
||||
} else {
|
||||
printInfo(t("packs.notInstalled", { name }));
|
||||
}
|
||||
emit({ pack: name, installed: removed ? "no" : "no" }, opts, STATE_SCHEMA);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
import { apiFetch } from "../api.mjs";
|
||||
import { t } from "../i18n.mjs";
|
||||
import { emit } from "../output.mjs";
|
||||
|
||||
const statusSchema = [
|
||||
{ key: "feed", header: "Feed" },
|
||||
{ key: "available", header: "Available" },
|
||||
{ key: "version", header: "Version" },
|
||||
{ key: "tier", header: "Tier" },
|
||||
{ key: "fetchedAt", header: "Fetched" },
|
||||
];
|
||||
|
||||
const syncSchema = [
|
||||
{ key: "feed", header: "Feed" },
|
||||
{ key: "status", header: "Status" },
|
||||
{ key: "version", header: "Version" },
|
||||
{ key: "reason", header: "Reason" },
|
||||
];
|
||||
|
||||
function exitCodeFor(response) {
|
||||
return Number.isInteger(response.exitCode) ? response.exitCode : response.status === 401 ? 4 : 1;
|
||||
}
|
||||
|
||||
export async function runRadarStatusCommand(opts = {}) {
|
||||
const response = await apiFetch("/api/radar/status", { acceptNotOk: true });
|
||||
if (!response.ok) return exitCodeFor(response);
|
||||
const data = await response.json();
|
||||
if (opts.output === "json") {
|
||||
emit(data, opts);
|
||||
return 0;
|
||||
}
|
||||
const rows = Object.entries(data.feeds ?? {}).map(([feed, value]) => ({
|
||||
feed,
|
||||
...(value && typeof value === "object" ? value : { available: false }),
|
||||
}));
|
||||
emit(rows, opts, statusSchema);
|
||||
return 0;
|
||||
}
|
||||
|
||||
export async function runRadarSyncCommand(opts = {}) {
|
||||
const response = await apiFetch("/api/radar/sync-all", {
|
||||
method: "POST",
|
||||
body: {},
|
||||
acceptNotOk: true,
|
||||
});
|
||||
if (!response.ok) return exitCodeFor(response);
|
||||
const data = await response.json();
|
||||
if (opts.output === "json") {
|
||||
emit(data, opts);
|
||||
return 0;
|
||||
}
|
||||
const rows = Object.entries(data).map(([feed, value]) => ({
|
||||
feed,
|
||||
...(value && typeof value === "object" ? value : { status: "error" }),
|
||||
}));
|
||||
emit(rows, opts, syncSchema);
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function registerRadar(program) {
|
||||
const radar = program.command("radar").description(t("radar.description"));
|
||||
radar
|
||||
.command("status")
|
||||
.description(t("radar.status"))
|
||||
.action(async (_opts, command) => {
|
||||
const code = await runRadarStatusCommand(command.optsWithGlobals());
|
||||
if (code !== 0) process.exitCode = code;
|
||||
});
|
||||
radar
|
||||
.command("sync")
|
||||
.description(t("radar.sync"))
|
||||
.action(async (_opts, command) => {
|
||||
const code = await runRadarSyncCommand(command.optsWithGlobals());
|
||||
if (code !== 0) process.exitCode = code;
|
||||
});
|
||||
}
|
||||
@@ -78,8 +78,6 @@ import { registerTokens } from "./tokens.mjs";
|
||||
import { registerConfigure } from "./configure.mjs";
|
||||
import { registerApiCommands } from "../api-commands/registry.mjs";
|
||||
import { registerPlugin } from "./plugin.mjs";
|
||||
import { registerRadar } from "./radar.mjs";
|
||||
import { registerPacks } from "./packs.mjs";
|
||||
|
||||
export function registerCommands(program) {
|
||||
registerMemory(program);
|
||||
@@ -163,6 +161,4 @@ export function registerCommands(program) {
|
||||
registerConfigure(program);
|
||||
registerApiCommands(program);
|
||||
registerPlugin(program);
|
||||
registerRadar(program);
|
||||
registerPacks(program);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import { join } from "node:path";
|
||||
import os from "node:os";
|
||||
import { printHeading, printInfo, printSuccess, printError, createPrompt } from "../io.mjs";
|
||||
import { resolveActiveContext } from "../contexts.mjs";
|
||||
import { guardHostConfigTarget } from "../utils/config-home-guard.mjs";
|
||||
|
||||
function stripToRoot(url) {
|
||||
const s = String(url || "").replace(/\/+$/, "");
|
||||
@@ -26,9 +25,7 @@ export function resolveAiderTarget(opts = {}) {
|
||||
if (opts.remote) root = stripToRoot(opts.remote);
|
||||
else {
|
||||
try {
|
||||
root = stripToRoot(
|
||||
resolveActiveContext(opts.context ?? process.env.OMNIROUTE_CONTEXT)?.baseUrl
|
||||
);
|
||||
root = stripToRoot(resolveActiveContext(opts.context ?? process.env.OMNIROUTE_CONTEXT)?.baseUrl);
|
||||
} catch {
|
||||
/* none */
|
||||
}
|
||||
@@ -81,7 +78,7 @@ async function fetchModelIds(apiBase, apiKey) {
|
||||
const res = await fetch(`${apiBase}/v1/models`, { headers, signal: AbortSignal.timeout(8000) });
|
||||
if (!res.ok) return [];
|
||||
const body = await res.json();
|
||||
const list = Array.isArray(body) ? body : (body.data ?? body.models ?? []);
|
||||
const list = Array.isArray(body) ? body : body.data ?? body.models ?? [];
|
||||
return list.map((m) => (typeof m === "string" ? m : m?.id)).filter(Boolean);
|
||||
} catch {
|
||||
return [];
|
||||
@@ -91,16 +88,7 @@ async function fetchModelIds(apiBase, apiKey) {
|
||||
export async function runSetupAiderCommand(opts = {}) {
|
||||
const { apiBase, apiKey } = resolveAiderTarget(opts);
|
||||
const dryRun = Boolean(opts.dryRun ?? opts["dry-run"]);
|
||||
const configPath =
|
||||
opts.configPath ?? opts["config-path"] ?? join(os.homedir(), ".aider.conf.yml");
|
||||
|
||||
const guard = await guardHostConfigTarget(configPath, {
|
||||
toolLabel: "Aider",
|
||||
hostCommand: "omniroute setup-aider",
|
||||
allowContainerWrite: Boolean(opts.allowContainerWrite ?? opts["allow-container-write"]),
|
||||
dryRun,
|
||||
});
|
||||
if (guard !== 0) return guard;
|
||||
const configPath = opts.configPath ?? opts["config-path"] ?? join(os.homedir(), ".aider.conf.yml");
|
||||
|
||||
printHeading("OmniRoute → Aider (openai-compatible via LiteLLM)");
|
||||
printInfo(`OPENAI_API_BASE: ${apiBase} (no /v1 — LiteLLM appends it)`);
|
||||
@@ -119,9 +107,7 @@ export async function runSetupAiderCommand(opts = {}) {
|
||||
}
|
||||
}
|
||||
if (!model) {
|
||||
printError(
|
||||
"A model is required. Pass --model <id> (the openai/ prefix is added automatically)."
|
||||
);
|
||||
printError("A model is required. Pass --model <id> (the openai/ prefix is added automatically).");
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -153,10 +139,6 @@ export function registerSetupAider(program) {
|
||||
.option("--config-path <path>", ".aider.conf.yml path (default: ~/.aider.conf.yml)")
|
||||
.option("--yes", "Non-interactive: do not prompt (requires --model)")
|
||||
.option("--dry-run", "Print what would be written without touching the filesystem")
|
||||
.option(
|
||||
"--allow-container-write",
|
||||
"Write even when the target is inside a container and not mounted from the host"
|
||||
)
|
||||
.action(async (opts) => {
|
||||
const code = await runSetupAiderCommand(opts);
|
||||
if (code !== 0) process.exit(code);
|
||||
|
||||
@@ -20,7 +20,6 @@ import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import os from "node:os";
|
||||
import { printHeading, printInfo, printSuccess, printError } from "../io.mjs";
|
||||
import { guardHostConfigTarget } from "../utils/config-home-guard.mjs";
|
||||
import {
|
||||
categoriseModel,
|
||||
isCodexCompatibleTextModel,
|
||||
@@ -148,14 +147,6 @@ export async function runSetupClaudeCommand(opts = {}) {
|
||||
printHeading("OmniRoute → Claude Code profile generator");
|
||||
printInfo(`Connecting to ${baseUrl} …`);
|
||||
|
||||
const guard = await guardHostConfigTarget(profilesRoot, {
|
||||
toolLabel: "Claude Code",
|
||||
hostCommand: "omniroute setup-claude",
|
||||
allowContainerWrite: Boolean(opts.allowContainerWrite ?? opts["allow-container-write"]),
|
||||
dryRun,
|
||||
});
|
||||
if (guard !== 0) return guard;
|
||||
|
||||
// ── Fetch model catalog ───────────────────────────────────────────────────
|
||||
let models;
|
||||
try {
|
||||
@@ -229,10 +220,6 @@ export function registerSetupClaude(program) {
|
||||
"Comma-separated substrings — only matching model IDs (e.g. glm,kimi)"
|
||||
)
|
||||
.option("--dry-run", "Print what would be written without touching the filesystem")
|
||||
.option(
|
||||
"--allow-container-write",
|
||||
"Write even when the target is inside a container and not mounted from the host"
|
||||
)
|
||||
.action(async (opts) => {
|
||||
const exitCode = await runSetupClaudeCommand(opts);
|
||||
if (exitCode !== 0) process.exit(exitCode);
|
||||
|
||||
@@ -16,7 +16,6 @@ import { join } from "node:path";
|
||||
import os from "node:os";
|
||||
import { printHeading, printInfo, printSuccess, printError, createPrompt } from "../io.mjs";
|
||||
import { resolveActiveContext } from "../contexts.mjs";
|
||||
import { guardHostConfigTarget } from "../utils/config-home-guard.mjs";
|
||||
|
||||
function stripToRoot(url) {
|
||||
let s = String(url || "").replace(/\/+$/, "");
|
||||
@@ -29,14 +28,11 @@ export function resolveClineTarget(opts = {}) {
|
||||
if (opts.remote) baseUrl = stripToRoot(opts.remote);
|
||||
else {
|
||||
try {
|
||||
baseUrl = stripToRoot(
|
||||
resolveActiveContext(opts.context ?? process.env.OMNIROUTE_CONTEXT)?.baseUrl
|
||||
);
|
||||
baseUrl = stripToRoot(resolveActiveContext(opts.context ?? process.env.OMNIROUTE_CONTEXT)?.baseUrl);
|
||||
} catch {
|
||||
/* none */
|
||||
}
|
||||
if (!baseUrl)
|
||||
baseUrl = `http://localhost:${Number(opts.port ?? process.env.PORT ?? 20128) || 20128}`;
|
||||
if (!baseUrl) baseUrl = `http://localhost:${Number(opts.port ?? process.env.PORT ?? 20128) || 20128}`;
|
||||
}
|
||||
let apiKey = opts.apiKey ?? opts["api-key"];
|
||||
if (!apiKey) {
|
||||
@@ -85,7 +81,7 @@ async function fetchModelIds(baseUrl, apiKey) {
|
||||
const res = await fetch(`${baseUrl}/v1/models`, { headers, signal: AbortSignal.timeout(8000) });
|
||||
if (!res.ok) return [];
|
||||
const body = await res.json();
|
||||
const list = Array.isArray(body) ? body : (body.data ?? body.models ?? []);
|
||||
const list = Array.isArray(body) ? body : body.data ?? body.models ?? [];
|
||||
return list.map((m) => (typeof m === "string" ? m : m?.id)).filter(Boolean);
|
||||
} catch {
|
||||
return [];
|
||||
@@ -97,14 +93,6 @@ export async function runSetupClineCommand(opts = {}) {
|
||||
const dryRun = Boolean(opts.dryRun ?? opts["dry-run"]);
|
||||
const clineDir = opts.clineDir ?? opts["cline-dir"] ?? join(os.homedir(), ".cline", "data");
|
||||
|
||||
const guard = await guardHostConfigTarget(clineDir, {
|
||||
toolLabel: "Cline",
|
||||
hostCommand: "omniroute setup-cline",
|
||||
allowContainerWrite: Boolean(opts.allowContainerWrite ?? opts["allow-container-write"]),
|
||||
dryRun,
|
||||
});
|
||||
if (guard !== 0) return guard;
|
||||
|
||||
printHeading("OmniRoute → Cline (OpenAI-compatible)");
|
||||
printInfo(`Server: ${baseUrl}`);
|
||||
|
||||
@@ -134,18 +122,7 @@ export async function runSetupClineCommand(opts = {}) {
|
||||
|
||||
if (dryRun) {
|
||||
console.log(`\n── [dry-run] ${gsPath} ──`);
|
||||
console.log(
|
||||
JSON.stringify(
|
||||
{
|
||||
actModeApiProvider: globalState.actModeApiProvider,
|
||||
planModeApiProvider: globalState.planModeApiProvider,
|
||||
openAiBaseUrl: globalState.openAiBaseUrl,
|
||||
openAiModelId: globalState.openAiModelId,
|
||||
},
|
||||
null,
|
||||
2
|
||||
)
|
||||
);
|
||||
console.log(JSON.stringify({ actModeApiProvider: globalState.actModeApiProvider, planModeApiProvider: globalState.planModeApiProvider, openAiBaseUrl: globalState.openAiBaseUrl, openAiModelId: globalState.openAiModelId }, null, 2));
|
||||
console.log(`\n── [dry-run] ${secPath} ── (openAiApiKey: ${apiKey ? "set" : "sk_omniroute"})`);
|
||||
} else {
|
||||
if (!existsSync(clineDir)) mkdirSync(clineDir, { recursive: true });
|
||||
@@ -156,9 +133,7 @@ export async function runSetupClineCommand(opts = {}) {
|
||||
}
|
||||
|
||||
// The VS Code extension uses opaque globalStorage — can't be file-written.
|
||||
printInfo(
|
||||
"\nFor the Cline VS Code extension, set these in its Settings → API (OpenAI Compatible):"
|
||||
);
|
||||
printInfo("\nFor the Cline VS Code extension, set these in its Settings → API (OpenAI Compatible):");
|
||||
printInfo(` Base URL: ${baseUrl} (NOT /v1 — Cline appends it)`);
|
||||
printInfo(` API Key: <your OMNIROUTE_API_KEY>`);
|
||||
printInfo(` Model: ${model}`);
|
||||
@@ -178,10 +153,6 @@ export function registerSetupCline(program) {
|
||||
.option("--cline-dir <dir>", "Cline data dir (default: ~/.cline/data)")
|
||||
.option("--yes", "Non-interactive: do not prompt (requires --model)")
|
||||
.option("--dry-run", "Print what would be written without touching the filesystem")
|
||||
.option(
|
||||
"--allow-container-write",
|
||||
"Write even when the target is inside a container and not mounted from the host"
|
||||
)
|
||||
.action(async (opts) => {
|
||||
const code = await runSetupClineCommand(opts);
|
||||
if (code !== 0) process.exit(code);
|
||||
|
||||
@@ -16,7 +16,6 @@ import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import os from "node:os";
|
||||
import { printHeading, printInfo, printSuccess, printError } from "../io.mjs";
|
||||
import { guardHostConfigTarget } from "../utils/config-home-guard.mjs";
|
||||
import { t } from "../i18n.mjs";
|
||||
|
||||
// ── Model categorisation ──────────────────────────────────────────────────────
|
||||
@@ -307,14 +306,6 @@ export async function runSetupCodexCommand(opts = {}) {
|
||||
const onlyFilter = opts.only ? opts.only.split(",").map((s) => s.trim()) : null;
|
||||
|
||||
printHeading(`OmniRoute → Codex CLI profile generator`);
|
||||
|
||||
const guard = await guardHostConfigTarget(codexHome, {
|
||||
toolLabel: "Codex",
|
||||
hostCommand: "omniroute setup-codex",
|
||||
allowContainerWrite: Boolean(opts.allowContainerWrite ?? opts["allow-container-write"]),
|
||||
dryRun,
|
||||
});
|
||||
if (guard !== 0) return guard;
|
||||
printInfo(`Connecting to ${baseUrl} …`);
|
||||
|
||||
// ── Fetch model catalog ───────────────────────────────────────────────────
|
||||
@@ -389,10 +380,6 @@ export function registerSetupCodex(program) {
|
||||
"Comma-separated substrings — only generate profiles for matching model IDs (e.g. glm,kimi)"
|
||||
)
|
||||
.option("--dry-run", "Print what would be written without touching the filesystem")
|
||||
.option(
|
||||
"--allow-container-write",
|
||||
"Write even when the target is inside a container and not mounted from the host"
|
||||
)
|
||||
.action(async (opts) => {
|
||||
const exitCode = await runSetupCodexCommand(opts);
|
||||
if (exitCode !== 0) process.exit(exitCode);
|
||||
|
||||
@@ -14,7 +14,6 @@ import os from "node:os";
|
||||
import { printHeading, printInfo, printSuccess, printError } from "../io.mjs";
|
||||
import { resolveActiveContext } from "../contexts.mjs";
|
||||
import { categoriseModel } from "./setup-codex.mjs";
|
||||
import { guardHostConfigTarget } from "../utils/config-home-guard.mjs";
|
||||
|
||||
const SECRET_REF = "${{ secrets.OMNIROUTE_API_KEY }}";
|
||||
|
||||
@@ -93,7 +92,7 @@ async function fetchModelIds(apiBase, apiKey) {
|
||||
});
|
||||
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
||||
const body = await res.json();
|
||||
const list = Array.isArray(body) ? body : (body.data ?? body.models ?? []);
|
||||
const list = Array.isArray(body) ? body : body.data ?? body.models ?? [];
|
||||
return list.map((m) => (typeof m === "string" ? m : m?.id)).filter(Boolean);
|
||||
} catch (e) {
|
||||
throw new Error(`Could not fetch models: ${e.message}`);
|
||||
@@ -103,22 +102,8 @@ async function fetchModelIds(apiBase, apiKey) {
|
||||
export async function runSetupContinueCommand(opts = {}) {
|
||||
const { apiBase, apiKey } = resolveContinueTarget(opts);
|
||||
const dryRun = Boolean(opts.dryRun ?? opts["dry-run"]);
|
||||
const only = opts.only
|
||||
? opts.only
|
||||
.split(",")
|
||||
.map((s) => s.trim())
|
||||
.filter(Boolean)
|
||||
: null;
|
||||
const configPath =
|
||||
opts.configPath ?? opts["config-path"] ?? join(os.homedir(), ".continue", "config.yaml");
|
||||
|
||||
const guard = await guardHostConfigTarget(configPath, {
|
||||
toolLabel: "Continue",
|
||||
hostCommand: "omniroute setup-continue",
|
||||
allowContainerWrite: Boolean(opts.allowContainerWrite ?? opts["allow-container-write"]),
|
||||
dryRun,
|
||||
});
|
||||
if (guard !== 0) return guard;
|
||||
const only = opts.only ? opts.only.split(",").map((s) => s.trim()).filter(Boolean) : null;
|
||||
const configPath = opts.configPath ?? opts["config-path"] ?? join(os.homedir(), ".continue", "config.yaml");
|
||||
|
||||
printHeading("OmniRoute → Continue (config.yaml)");
|
||||
printInfo(`apiBase: ${apiBase}`);
|
||||
@@ -165,7 +150,7 @@ export async function runSetupContinueCommand(opts = {}) {
|
||||
printInfo("\nProvide the key (config.yaml references it, not stores it):");
|
||||
printInfo(" cn CLI: export OMNIROUTE_API_KEY=... (read from your shell)");
|
||||
printInfo(" IDE: echo 'OMNIROUTE_API_KEY=...' >> ~/.continue/.env");
|
||||
printInfo('Run: cn -p "reply OK"');
|
||||
printInfo("Run: cn -p \"reply OK\"");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -181,10 +166,6 @@ export function registerSetupContinue(program) {
|
||||
.option("--only <patterns>", "Comma-separated substrings — keep only matching model IDs")
|
||||
.option("--config-path <path>", "config.yaml path (default: ~/.continue/config.yaml)")
|
||||
.option("--dry-run", "Print what would be written without touching the filesystem")
|
||||
.option(
|
||||
"--allow-container-write",
|
||||
"Write even when the target is inside a container and not mounted from the host"
|
||||
)
|
||||
.action(async (opts) => {
|
||||
const code = await runSetupContinueCommand(opts);
|
||||
if (code !== 0) process.exit(code);
|
||||
|
||||
@@ -13,7 +13,6 @@ import os from "node:os";
|
||||
import { printHeading, printInfo, printSuccess, printError } from "../io.mjs";
|
||||
import { resolveActiveContext } from "../contexts.mjs";
|
||||
import { categoriseModel } from "./setup-codex.mjs";
|
||||
import { guardHostConfigTarget } from "../utils/config-home-guard.mjs";
|
||||
|
||||
const API_KEY_REF = "$OMNIROUTE_API_KEY";
|
||||
|
||||
@@ -88,29 +87,15 @@ async function fetchModelIds(baseUrl, apiKey) {
|
||||
});
|
||||
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
||||
const body = await res.json();
|
||||
const list = Array.isArray(body) ? body : (body.data ?? body.models ?? []);
|
||||
const list = Array.isArray(body) ? body : body.data ?? body.models ?? [];
|
||||
return list.map((m) => (typeof m === "string" ? m : m?.id)).filter(Boolean);
|
||||
}
|
||||
|
||||
export async function runSetupCrushCommand(opts = {}) {
|
||||
const { baseUrl, apiKey } = resolveCrushTarget(opts);
|
||||
const dryRun = Boolean(opts.dryRun ?? opts["dry-run"]);
|
||||
const only = opts.only
|
||||
? opts.only
|
||||
.split(",")
|
||||
.map((s) => s.trim())
|
||||
.filter(Boolean)
|
||||
: null;
|
||||
const configPath =
|
||||
opts.configPath ?? opts["config-path"] ?? join(os.homedir(), ".config", "crush", "crush.json");
|
||||
|
||||
const guard = await guardHostConfigTarget(configPath, {
|
||||
toolLabel: "Crush",
|
||||
hostCommand: "omniroute setup-crush",
|
||||
allowContainerWrite: Boolean(opts.allowContainerWrite ?? opts["allow-container-write"]),
|
||||
dryRun,
|
||||
});
|
||||
if (guard !== 0) return guard;
|
||||
const only = opts.only ? opts.only.split(",").map((s) => s.trim()).filter(Boolean) : null;
|
||||
const configPath = opts.configPath ?? opts["config-path"] ?? join(os.homedir(), ".config", "crush", "crush.json");
|
||||
|
||||
printHeading("OmniRoute → Crush (openai-compat)");
|
||||
printInfo(`base_url: ${baseUrl}`);
|
||||
@@ -135,17 +120,13 @@ export async function runSetupCrushCommand(opts = {}) {
|
||||
|
||||
if (dryRun) {
|
||||
console.log("\n" + (out.length > 3500 ? out.slice(0, 3500) + "\n… (truncated)" : out));
|
||||
printInfo(
|
||||
`[dry-run] ${provider.models.length} model(s) under providers.omniroute → ${configPath}`
|
||||
);
|
||||
printInfo(`[dry-run] ${provider.models.length} model(s) under providers.omniroute → ${configPath}`);
|
||||
return 0;
|
||||
}
|
||||
mkdirSync(join(configPath, ".."), { recursive: true });
|
||||
writeFileSync(configPath, out, "utf8");
|
||||
printSuccess(`Wrote ${configPath} (${provider.models.length} models under providers.omniroute)`);
|
||||
printInfo(
|
||||
"Provide the key (config references $OMNIROUTE_API_KEY): export OMNIROUTE_API_KEY=..."
|
||||
);
|
||||
printInfo("Provide the key (config references $OMNIROUTE_API_KEY): export OMNIROUTE_API_KEY=...");
|
||||
printInfo("Then run: crush");
|
||||
return 0;
|
||||
}
|
||||
@@ -160,10 +141,6 @@ export function registerSetupCrush(program) {
|
||||
.option("--only <patterns>", "Comma-separated substrings — keep only matching model IDs")
|
||||
.option("--config-path <path>", "crush.json path (default: ~/.config/crush/crush.json)")
|
||||
.option("--dry-run", "Print what would be written without touching the filesystem")
|
||||
.option(
|
||||
"--allow-container-write",
|
||||
"Write even when the target is inside a container and not mounted from the host"
|
||||
)
|
||||
.action(async (opts) => {
|
||||
const code = await runSetupCrushCommand(opts);
|
||||
if (code !== 0) process.exit(code);
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
import { printHeading, printInfo, printSuccess } from "../io.mjs";
|
||||
import { resolveActiveContext } from "../contexts.mjs";
|
||||
import { isContainerRuntime } from "../utils/config-home-guard.mjs";
|
||||
|
||||
function ensureV1(url) {
|
||||
const s = String(url || "").replace(/\/+$/, "");
|
||||
@@ -72,7 +71,7 @@ async function fetchModelIds(apiBase, apiKey) {
|
||||
});
|
||||
if (!res.ok) return [];
|
||||
const body = await res.json();
|
||||
const list = Array.isArray(body) ? body : (body.data ?? body.models ?? []);
|
||||
const list = Array.isArray(body) ? body : body.data ?? body.models ?? [];
|
||||
return list.map((m) => (typeof m === "string" ? m : m?.id)).filter(Boolean);
|
||||
} catch {
|
||||
return [];
|
||||
@@ -85,32 +84,19 @@ export async function runSetupCursorCommand(opts = {}) {
|
||||
printInfo(`Server: ${apiBase}`);
|
||||
|
||||
let models = [];
|
||||
const only = opts.only
|
||||
? opts.only
|
||||
.split(",")
|
||||
.map((s) => s.trim())
|
||||
.filter(Boolean)
|
||||
: null;
|
||||
const only = opts.only ? opts.only.split(",").map((s) => s.trim()).filter(Boolean) : null;
|
||||
const ids = await fetchModelIds(apiBase, apiKey);
|
||||
models = only ? ids.filter((id) => only.some((f) => id.includes(f))) : ids;
|
||||
|
||||
console.log("\n" + buildCursorInstructions({ apiBase, models }));
|
||||
printSuccess("\nCursor is configured manually (no file written — Cursor's storage is opaque).");
|
||||
if (await isContainerRuntime()) {
|
||||
printInfo(
|
||||
"Note: this ran inside a container, so the base URL above is the container's own view. " +
|
||||
"Use the address the host reaches OmniRoute on (e.g. the published port) in Cursor's settings."
|
||||
);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function registerSetupCursor(program) {
|
||||
program
|
||||
.command("setup-cursor")
|
||||
.description(
|
||||
"Print the steps to point Cursor at OmniRoute (chat panel; Cursor config is not file-writable)"
|
||||
)
|
||||
.description("Print the steps to point Cursor at OmniRoute (chat panel; Cursor config is not file-writable)")
|
||||
.option("--port <port>", "Local OmniRoute port (ignored when --remote is set)", "20128")
|
||||
.option("--remote <url>", "Remote OmniRoute URL, e.g. http://192.168.0.15:20128")
|
||||
.option("--api-key <key>", "OmniRoute API key (defaults to OMNIROUTE_API_KEY env var)")
|
||||
|
||||
@@ -14,7 +14,6 @@ import { join } from "node:path";
|
||||
import os from "node:os";
|
||||
import { printHeading, printInfo, printSuccess, printError, createPrompt } from "../io.mjs";
|
||||
import { resolveActiveContext } from "../contexts.mjs";
|
||||
import { guardHostConfigTarget } from "../utils/config-home-guard.mjs";
|
||||
|
||||
function stripToRoot(url) {
|
||||
const s = String(url || "").replace(/\/+$/, "");
|
||||
@@ -27,9 +26,7 @@ export function resolveGooseTarget(opts = {}) {
|
||||
if (opts.remote) root = stripToRoot(opts.remote);
|
||||
else {
|
||||
try {
|
||||
root = stripToRoot(
|
||||
resolveActiveContext(opts.context ?? process.env.OMNIROUTE_CONTEXT)?.baseUrl
|
||||
);
|
||||
root = stripToRoot(resolveActiveContext(opts.context ?? process.env.OMNIROUTE_CONTEXT)?.baseUrl);
|
||||
} catch {
|
||||
/* none */
|
||||
}
|
||||
@@ -83,7 +80,7 @@ async function fetchModelIds(host, apiKey) {
|
||||
const res = await fetch(`${host}/v1/models`, { headers, signal: AbortSignal.timeout(8000) });
|
||||
if (!res.ok) return [];
|
||||
const body = await res.json();
|
||||
const list = Array.isArray(body) ? body : (body.data ?? body.models ?? []);
|
||||
const list = Array.isArray(body) ? body : body.data ?? body.models ?? [];
|
||||
return list.map((m) => (typeof m === "string" ? m : m?.id)).filter(Boolean);
|
||||
} catch {
|
||||
return [];
|
||||
@@ -93,16 +90,7 @@ async function fetchModelIds(host, apiKey) {
|
||||
export async function runSetupGooseCommand(opts = {}) {
|
||||
const { host, apiKey } = resolveGooseTarget(opts);
|
||||
const dryRun = Boolean(opts.dryRun ?? opts["dry-run"]);
|
||||
const configPath =
|
||||
opts.configPath ?? opts["config-path"] ?? join(os.homedir(), ".config", "goose", "config.yaml");
|
||||
|
||||
const guard = await guardHostConfigTarget(configPath, {
|
||||
toolLabel: "Goose",
|
||||
hostCommand: "omniroute setup-goose",
|
||||
allowContainerWrite: Boolean(opts.allowContainerWrite ?? opts["allow-container-write"]),
|
||||
dryRun,
|
||||
});
|
||||
if (guard !== 0) return guard;
|
||||
const configPath = opts.configPath ?? opts["config-path"] ?? join(os.homedir(), ".config", "goose", "config.yaml");
|
||||
|
||||
printHeading("OmniRoute → Goose (openai-compatible)");
|
||||
printInfo(`OPENAI_HOST: ${host} (no /v1 — Goose appends it)`);
|
||||
@@ -140,16 +128,14 @@ export async function runSetupGooseCommand(opts = {}) {
|
||||
|
||||
printInfo("\nProvide the key (Goose reads it from the env / OS keyring):");
|
||||
console.log(buildGooseEnvRecipe({ host, model }));
|
||||
printInfo('Then run: goose session (or: goose run -t "reply OK")');
|
||||
printInfo("Then run: goose session (or: goose run -t \"reply OK\")");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function registerSetupGoose(program) {
|
||||
program
|
||||
.command("setup-goose")
|
||||
.description(
|
||||
"Configure Goose for OmniRoute: write ~/.config/goose/config.yaml + print the env recipe"
|
||||
)
|
||||
.description("Configure Goose for OmniRoute: write ~/.config/goose/config.yaml + print the env recipe")
|
||||
.option("--port <port>", "Local OmniRoute port (ignored when --remote is set)", "20128")
|
||||
.option("--remote <url>", "Remote OmniRoute URL, e.g. http://192.168.0.15:20128")
|
||||
.option("--api-key <key>", "OmniRoute API key (defaults to OMNIROUTE_API_KEY env var)")
|
||||
@@ -157,10 +143,6 @@ export function registerSetupGoose(program) {
|
||||
.option("--config-path <path>", "config.yaml path (default: ~/.config/goose/config.yaml)")
|
||||
.option("--yes", "Non-interactive: do not prompt (requires --model)")
|
||||
.option("--dry-run", "Print what would be written without touching the filesystem")
|
||||
.option(
|
||||
"--allow-container-write",
|
||||
"Write even when the target is inside a container and not mounted from the host"
|
||||
)
|
||||
.action(async (opts) => {
|
||||
const code = await runSetupGooseCommand(opts);
|
||||
if (code !== 0) process.exit(code);
|
||||
|
||||
@@ -14,7 +14,6 @@ import { join } from "node:path";
|
||||
import os from "node:os";
|
||||
import { printHeading, printInfo, printSuccess, printError, createPrompt } from "../io.mjs";
|
||||
import { resolveActiveContext } from "../contexts.mjs";
|
||||
import { guardHostConfigTarget } from "../utils/config-home-guard.mjs";
|
||||
|
||||
/** Ensure the URL ends with /v1 (Kilo appends /chat/completions to it). */
|
||||
function ensureV1(url) {
|
||||
@@ -62,11 +61,7 @@ export function buildKiloAuth(existing, { apiKey, baseUrl, model }) {
|
||||
/** Merge the kilocode.* keys into VS Code settings.json (extension surface). */
|
||||
export function buildKiloVscodeSettings(existing, { apiKey, baseUrl, model }) {
|
||||
const s = { ...(existing || {}) };
|
||||
s["kilocode.customProvider"] = {
|
||||
name: "OmniRoute",
|
||||
baseURL: baseUrl,
|
||||
apiKey: apiKey || "sk_omniroute",
|
||||
};
|
||||
s["kilocode.customProvider"] = { name: "OmniRoute", baseURL: baseUrl, apiKey: apiKey || "sk_omniroute" };
|
||||
s["kilocode.defaultModel"] = model;
|
||||
return s;
|
||||
}
|
||||
@@ -90,7 +85,7 @@ async function fetchModelIds(root, apiKey) {
|
||||
});
|
||||
if (!res.ok) return [];
|
||||
const body = await res.json();
|
||||
const list = Array.isArray(body) ? body : (body.data ?? body.models ?? []);
|
||||
const list = Array.isArray(body) ? body : body.data ?? body.models ?? [];
|
||||
return list.map((m) => (typeof m === "string" ? m : m?.id)).filter(Boolean);
|
||||
} catch {
|
||||
return [];
|
||||
@@ -100,22 +95,9 @@ async function fetchModelIds(root, apiKey) {
|
||||
export async function runSetupKiloCommand(opts = {}) {
|
||||
const { baseUrl, apiKey } = resolveKiloTarget(opts);
|
||||
const dryRun = Boolean(opts.dryRun ?? opts["dry-run"]);
|
||||
const authPath =
|
||||
opts.authPath ??
|
||||
opts["auth-path"] ??
|
||||
join(os.homedir(), ".local", "share", "kilo", "auth.json");
|
||||
|
||||
const guard = await guardHostConfigTarget(authPath, {
|
||||
toolLabel: "Kilo Code",
|
||||
hostCommand: "omniroute setup-kilo",
|
||||
allowContainerWrite: Boolean(opts.allowContainerWrite ?? opts["allow-container-write"]),
|
||||
dryRun,
|
||||
});
|
||||
if (guard !== 0) return guard;
|
||||
const authPath = opts.authPath ?? opts["auth-path"] ?? join(os.homedir(), ".local", "share", "kilo", "auth.json");
|
||||
const vscodePath =
|
||||
opts.vscodeSettings ??
|
||||
opts["vscode-settings"] ??
|
||||
join(os.homedir(), ".config", "Code", "User", "settings.json");
|
||||
opts.vscodeSettings ?? opts["vscode-settings"] ?? join(os.homedir(), ".config", "Code", "User", "settings.json");
|
||||
|
||||
printHeading("OmniRoute → Kilo Code (OpenAI-compatible)");
|
||||
printInfo(`Server: ${baseUrl}`);
|
||||
@@ -134,9 +116,7 @@ export async function runSetupKiloCommand(opts = {}) {
|
||||
}
|
||||
}
|
||||
if (!model) {
|
||||
printError(
|
||||
"A model is required. Pass --model <id> (Kilo's extension has no model auto-discovery)."
|
||||
);
|
||||
printError("A model is required. Pass --model <id> (Kilo's extension has no model auto-discovery).");
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -152,19 +132,12 @@ export async function runSetupKiloCommand(opts = {}) {
|
||||
console.log(`\n── [dry-run] ${authPath} ──`);
|
||||
console.log(
|
||||
JSON.stringify(
|
||||
{
|
||||
"openai-compatible": {
|
||||
...auth["openai-compatible"],
|
||||
apiKey: apiKey ? "set" : "sk_omniroute",
|
||||
},
|
||||
},
|
||||
{ "openai-compatible": { ...auth["openai-compatible"], apiKey: apiKey ? "set" : "sk_omniroute" } },
|
||||
null,
|
||||
2
|
||||
)
|
||||
);
|
||||
console.log(
|
||||
`\n── [dry-run] ${vscodePath} ── ${vscodeExists ? "(would merge kilocode.* keys)" : "(skipped — file absent)"}`
|
||||
);
|
||||
console.log(`\n── [dry-run] ${vscodePath} ── ${vscodeExists ? "(would merge kilocode.* keys)" : "(skipped — file absent)"}`);
|
||||
} else {
|
||||
mkdirSync(join(authPath, ".."), { recursive: true });
|
||||
writeFileSync(authPath, JSON.stringify(auth, null, 2) + "\n", "utf8");
|
||||
@@ -194,20 +167,10 @@ export function registerSetupKilo(program) {
|
||||
.option("--remote <url>", "Remote OmniRoute URL, e.g. http://192.168.0.15:20128")
|
||||
.option("--api-key <key>", "OmniRoute API key (defaults to OMNIROUTE_API_KEY env var)")
|
||||
.option("--model <id>", "Model id for Kilo (required unless picked interactively)")
|
||||
.option(
|
||||
"--auth-path <path>",
|
||||
"Kilo CLI auth.json path (default: ~/.local/share/kilo/auth.json)"
|
||||
)
|
||||
.option(
|
||||
"--vscode-settings <path>",
|
||||
"VS Code settings.json (default: ~/.config/Code/User/settings.json)"
|
||||
)
|
||||
.option("--auth-path <path>", "Kilo CLI auth.json path (default: ~/.local/share/kilo/auth.json)")
|
||||
.option("--vscode-settings <path>", "VS Code settings.json (default: ~/.config/Code/User/settings.json)")
|
||||
.option("--yes", "Non-interactive: do not prompt (requires --model)")
|
||||
.option("--dry-run", "Print what would be written without touching the filesystem")
|
||||
.option(
|
||||
"--allow-container-write",
|
||||
"Write even when the target is inside a container and not mounted from the host"
|
||||
)
|
||||
.action(async (opts) => {
|
||||
const code = await runSetupKiloCommand(opts);
|
||||
if (code !== 0) process.exit(code);
|
||||
|
||||
@@ -30,7 +30,6 @@ import os from "node:os";
|
||||
import { printHeading, printInfo, printSuccess, printError } from "../io.mjs";
|
||||
import { t } from "../i18n.mjs";
|
||||
import { resolveActiveContext } from "../contexts.mjs";
|
||||
import { guardHostConfigTarget } from "../utils/config-home-guard.mjs";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
@@ -317,13 +316,6 @@ export async function runSetupOpenCodeCommand(opts = {}) {
|
||||
printInfo(`OpenCode config dir: ${opencodeConfigDir}`);
|
||||
printInfo(`OpenCode data dir: ${opencodeDataDir}`);
|
||||
|
||||
const guard = await guardHostConfigTarget(opencodeConfigDir, {
|
||||
toolLabel: "OpenCode",
|
||||
hostCommand: "omniroute setup opencode",
|
||||
allowContainerWrite: Boolean(opts.allowContainerWrite ?? opts["allow-container-write"]),
|
||||
});
|
||||
if (guard !== 0) return { exitCode: guard };
|
||||
|
||||
// 1. Resolve bundled plugin
|
||||
let pluginInfo;
|
||||
try {
|
||||
@@ -428,10 +420,6 @@ export function registerSetupOpenCode(setupCommand) {
|
||||
false
|
||||
)
|
||||
.option("--non-interactive", "Do not prompt; skip the auth login step", false)
|
||||
.option(
|
||||
"--allow-container-write",
|
||||
"Write even when the target is inside a container and not mounted from the host"
|
||||
)
|
||||
.action(async (opts, cmd) => {
|
||||
// The parent `setup` command uses cmd.optsWithGlobals(); we mirror
|
||||
// that here so global flags (--json, --base-url, --api-key) still
|
||||
|
||||
@@ -14,7 +14,6 @@ import { basename, dirname } from "node:path";
|
||||
import { applyEdits, modify, parse, printParseErrorCode } from "jsonc-parser";
|
||||
import { printHeading, printInfo, printSuccess, printError } from "../io.mjs";
|
||||
import { resolveActiveContext } from "../contexts.mjs";
|
||||
import { guardHostConfigTarget } from "../utils/config-home-guard.mjs";
|
||||
|
||||
const ENV_KEY_REF = "{env:OMNIROUTE_API_KEY}";
|
||||
const JSON_FORMATTING_OPTIONS = { insertSpaces: true, tabSize: 2 };
|
||||
@@ -120,15 +119,6 @@ export async function runSetupOpencodeCommand(opts = {}) {
|
||||
const { resolveOpencodeConfigPath } =
|
||||
await import("../../../src/shared/services/opencodeConfigPath.ts");
|
||||
configPath = resolveOpencodeConfigPath();
|
||||
|
||||
const guard = await guardHostConfigTarget(configPath, {
|
||||
toolLabel: "OpenCode",
|
||||
hostCommand: "omniroute setup-opencode",
|
||||
allowContainerWrite: Boolean(opts.allowContainerWrite ?? opts["allow-container-write"]),
|
||||
dryRun,
|
||||
});
|
||||
if (guard !== 0) return guard;
|
||||
|
||||
raw = await generateOpencodeConfig({
|
||||
baseUrl,
|
||||
apiKey,
|
||||
@@ -173,10 +163,6 @@ export function registerSetupOpencode(program) {
|
||||
.option("--model <id>", "Set the default top-level model (omniroute/<id>)")
|
||||
.option("--only <patterns>", "Comma-separated substrings — keep only matching model IDs")
|
||||
.option("--dry-run", "Print what would be written without touching the filesystem")
|
||||
.option(
|
||||
"--allow-container-write",
|
||||
"Write even when the target is inside a container and not mounted from the host"
|
||||
)
|
||||
.action(async (opts) => {
|
||||
const code = await runSetupOpencodeCommand(opts);
|
||||
if (code !== 0) process.exit(code);
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
normalizeQwenCodeBaseUrl,
|
||||
} from "../../../src/shared/services/qwenCodeConfig.ts";
|
||||
import { resolveActiveContext } from "../contexts.mjs";
|
||||
import { guardHostConfigTarget } from "../utils/config-home-guard.mjs";
|
||||
import { createPrompt, printError, printHeading, printInfo, printSuccess } from "../io.mjs";
|
||||
|
||||
/** Resolve base URL and key from flags, active context, then local defaults. */
|
||||
@@ -103,16 +102,6 @@ export async function runSetupQwenCommand(opts = {}) {
|
||||
printHeading("OmniRoute → Qwen Code (OpenAI-compatible)");
|
||||
printInfo(`baseUrl: ${baseUrl}`);
|
||||
|
||||
for (const target of [settingsPath, envPath]) {
|
||||
const guard = await guardHostConfigTarget(target, {
|
||||
toolLabel: "Qwen Code",
|
||||
hostCommand: "omniroute setup-qwen",
|
||||
allowContainerWrite: Boolean(opts.allowContainerWrite ?? opts["allow-container-write"]),
|
||||
dryRun,
|
||||
});
|
||||
if (guard !== 0) return guard;
|
||||
}
|
||||
|
||||
let model = String(opts.model || "").trim();
|
||||
if (!model && !opts.yes) {
|
||||
const modelIds = await fetchModelIds(baseUrl, apiKey);
|
||||
@@ -170,10 +159,6 @@ export function registerSetupQwen(program) {
|
||||
.option("--env-path <path>", "Qwen Code .env path")
|
||||
.option("--yes", "Non-interactive; requires --model")
|
||||
.option("--dry-run", "Print settings without writing files or secrets")
|
||||
.option(
|
||||
"--allow-container-write",
|
||||
"Write even when the target is inside a container and not mounted from the host"
|
||||
)
|
||||
.action(async (opts) => {
|
||||
const code = await runSetupQwenCommand(opts);
|
||||
if (code !== 0) process.exitCode = code;
|
||||
|
||||
@@ -16,7 +16,6 @@ import { join } from "node:path";
|
||||
import os from "node:os";
|
||||
import { printHeading, printInfo, printSuccess, printError } from "../io.mjs";
|
||||
import { resolveActiveContext } from "../contexts.mjs";
|
||||
import { guardHostConfigTarget } from "../utils/config-home-guard.mjs";
|
||||
|
||||
function ensureV1(url) {
|
||||
const s = String(url || "").replace(/\/+$/, "");
|
||||
@@ -90,7 +89,7 @@ async function fetchModelIds(baseUrl, apiKey) {
|
||||
});
|
||||
if (!res.ok) return [];
|
||||
const body = await res.json();
|
||||
const list = Array.isArray(body) ? body : (body.data ?? body.models ?? []);
|
||||
const list = Array.isArray(body) ? body : body.data ?? body.models ?? [];
|
||||
return list.map((m) => (typeof m === "string" ? m : m?.id)).filter(Boolean);
|
||||
} catch {
|
||||
return [];
|
||||
@@ -100,20 +99,9 @@ async function fetchModelIds(baseUrl, apiKey) {
|
||||
export async function runSetupRooCommand(opts = {}) {
|
||||
const { baseUrl, apiKey } = resolveRooTarget(opts);
|
||||
const dryRun = Boolean(opts.dryRun ?? opts["dry-run"]);
|
||||
const importPath =
|
||||
opts.importPath ?? opts["import-path"] ?? join(os.homedir(), ".omniroute", "roo-settings.json");
|
||||
|
||||
const guard = await guardHostConfigTarget(importPath, {
|
||||
toolLabel: "Roo Code",
|
||||
hostCommand: "omniroute setup-roo",
|
||||
allowContainerWrite: Boolean(opts.allowContainerWrite ?? opts["allow-container-write"]),
|
||||
dryRun,
|
||||
});
|
||||
if (guard !== 0) return guard;
|
||||
const importPath = opts.importPath ?? opts["import-path"] ?? join(os.homedir(), ".omniroute", "roo-settings.json");
|
||||
const vscodePath =
|
||||
opts.vscodeSettings ??
|
||||
opts["vscode-settings"] ??
|
||||
join(os.homedir(), ".config", "Code", "User", "settings.json");
|
||||
opts.vscodeSettings ?? opts["vscode-settings"] ?? join(os.homedir(), ".config", "Code", "User", "settings.json");
|
||||
|
||||
printHeading("OmniRoute → Roo Code (OpenAI-compatible)");
|
||||
printInfo(`Server: ${baseUrl}`);
|
||||
@@ -142,27 +130,8 @@ export async function runSetupRooCommand(opts = {}) {
|
||||
|
||||
if (dryRun) {
|
||||
console.log(`\n── [dry-run] ${importPath} ──`);
|
||||
console.log(
|
||||
JSON.stringify(
|
||||
{
|
||||
...importDoc,
|
||||
providerProfiles: {
|
||||
...importDoc.providerProfiles,
|
||||
apiConfigs: {
|
||||
OmniRoute: {
|
||||
...importDoc.providerProfiles.apiConfigs.OmniRoute,
|
||||
openAiApiKey: apiKey ? "set" : "sk_omniroute",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
null,
|
||||
2
|
||||
)
|
||||
);
|
||||
console.log(
|
||||
`\n── [dry-run] ${vscodePath} ── ${vscodeExists ? "(would set roo-cline.autoImportSettingsPath)" : "(skipped — file absent)"}`
|
||||
);
|
||||
console.log(JSON.stringify({ ...importDoc, providerProfiles: { ...importDoc.providerProfiles, apiConfigs: { OmniRoute: { ...importDoc.providerProfiles.apiConfigs.OmniRoute, openAiApiKey: apiKey ? "set" : "sk_omniroute" } } } }, null, 2));
|
||||
console.log(`\n── [dry-run] ${vscodePath} ── ${vscodeExists ? "(would set roo-cline.autoImportSettingsPath)" : "(skipped — file absent)"}`);
|
||||
} else {
|
||||
mkdirSync(join(importPath, ".."), { recursive: true });
|
||||
writeFileSync(importPath, JSON.stringify(importDoc, null, 2) + "\n", "utf8");
|
||||
@@ -192,20 +161,10 @@ export function registerSetupRoo(program) {
|
||||
.option("--remote <url>", "Remote OmniRoute URL, e.g. http://192.168.0.15:20128")
|
||||
.option("--api-key <key>", "OmniRoute API key (defaults to OMNIROUTE_API_KEY env var)")
|
||||
.option("--model <id>", "Model id for Roo (required unless picked interactively)")
|
||||
.option(
|
||||
"--import-path <path>",
|
||||
"Roo import JSON path (default: ~/.omniroute/roo-settings.json)"
|
||||
)
|
||||
.option(
|
||||
"--vscode-settings <path>",
|
||||
"VS Code settings.json (default: ~/.config/Code/User/settings.json)"
|
||||
)
|
||||
.option("--import-path <path>", "Roo import JSON path (default: ~/.omniroute/roo-settings.json)")
|
||||
.option("--vscode-settings <path>", "VS Code settings.json (default: ~/.config/Code/User/settings.json)")
|
||||
.option("--yes", "Non-interactive: do not prompt (requires --model)")
|
||||
.option("--dry-run", "Print what would be written without touching the filesystem")
|
||||
.option(
|
||||
"--allow-container-write",
|
||||
"Write even when the target is inside a container and not mounted from the host"
|
||||
)
|
||||
.action(async (opts) => {
|
||||
const code = await runSetupRooCommand(opts);
|
||||
if (code !== 0) process.exit(code);
|
||||
|
||||
@@ -921,11 +921,6 @@
|
||||
"model": "Filter by model"
|
||||
}
|
||||
},
|
||||
"radar": {
|
||||
"description": "Inspect and synchronize the local Radar catalog feeds",
|
||||
"status": "Show local Radar settings and feed cache status",
|
||||
"sync": "Synchronize catalog, referrals, offers, and Intel through the local server"
|
||||
},
|
||||
"resilience": {
|
||||
"description": "Inspect and manage resilience mechanisms",
|
||||
"status": {
|
||||
@@ -1304,23 +1299,5 @@
|
||||
},
|
||||
"setupCodex": {
|
||||
"description": "Generate ~/.codex profile files from OmniRoute live model catalog"
|
||||
},
|
||||
"packs": {
|
||||
"description": "Manage optional runtime packs (ML / browser automation)",
|
||||
"listDescription": "List optional packs and their install state",
|
||||
"installDescription": "Install an optional pack into DATA_DIR",
|
||||
"verifyDescription": "Verify installed packs against the shipped checksum index",
|
||||
"removeDescription": "Remove an installed optional pack",
|
||||
"sourceOpt": "Directory holding pack payloads and the pack index",
|
||||
"warnNoIndex": "optional-packs.index.json not found — install/verify are unavailable in this checkout (desktop bundles ship it)",
|
||||
"errUnknown": "unknown pack: {name}",
|
||||
"errNoIndex": "pack index not found; pass --source <dir> holding the pack payload (desktop bundles ship it next to the app)",
|
||||
"installed": "pack \"{name}\" installed and verified at {dir}",
|
||||
"restartHint": "restart the OmniRoute server (or desktop app) so the runtime picks the pack up",
|
||||
"removed": "pack \"{name}\" removed",
|
||||
"notInstalled": "pack \"{name}\" was not installed",
|
||||
"verifyOk": "all installed packs verified",
|
||||
"verifyFailed": "{count} pack(s) failed verification",
|
||||
"noneInstalled": "no optional packs installed"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -918,11 +918,6 @@
|
||||
"model": "Filtrar por model"
|
||||
}
|
||||
},
|
||||
"radar": {
|
||||
"description": "Inspecionar e sincronizar os feeds locais do catálogo Radar",
|
||||
"status": "Mostrar configurações locais e estado dos caches do Radar",
|
||||
"sync": "Sincronizar catálogo, indicações, ofertas e Intel pelo servidor local"
|
||||
},
|
||||
"resilience": {
|
||||
"description": "Inspecionar e gerenciar mecanismos de resiliência",
|
||||
"status": {
|
||||
@@ -1301,23 +1296,5 @@
|
||||
},
|
||||
"setupCodex": {
|
||||
"description": "Gera os arquivos de perfil ~/.codex a partir do catálogo de modelos ao vivo do OmniRoute"
|
||||
},
|
||||
"packs": {
|
||||
"description": "Gerencia packs opcionais de runtime (ML / automação de navegador)",
|
||||
"listDescription": "Lista os packs opcionais e seu estado de instalação",
|
||||
"installDescription": "Instala um pack opcional no DATA_DIR",
|
||||
"verifyDescription": "Verifica os packs instalados contra o índice de checksums embarcado",
|
||||
"removeDescription": "Remove um pack opcional instalado",
|
||||
"sourceOpt": "Diretório com os payloads dos packs e o índice de packs",
|
||||
"warnNoIndex": "optional-packs.index.json não encontrado — install/verify indisponíveis neste checkout (instaladores desktop o embarcam)",
|
||||
"errUnknown": "pack desconhecido: {name}",
|
||||
"errNoIndex": "índice de packs não encontrado; passe --source <dir> com o payload do pack (instaladores desktop o embarcam ao lado do app)",
|
||||
"installed": "pack \"{name}\" instalado e verificado em {dir}",
|
||||
"restartHint": "reinicie o servidor OmniRoute (ou o app desktop) para o runtime reconhecer o pack",
|
||||
"removed": "pack \"{name}\" removido",
|
||||
"notInstalled": "o pack \"{name}\" não estava instalado",
|
||||
"verifyOk": "todos os packs instalados verificados",
|
||||
"verifyFailed": "{count} pack(s) falharam na verificação",
|
||||
"noneInstalled": "nenhum pack opcional instalado"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
import { printError, printInfo } from "../io.mjs";
|
||||
|
||||
/**
|
||||
* Container guard for CLI-tool config writes.
|
||||
*
|
||||
* `omniroute setup-*` writes to `~/.codex`, `~/.claude`, ... — paths that only
|
||||
* mean something on the operator's host. Run the same command inside the
|
||||
* OmniRoute container and the write "succeeds" into an ephemeral layer that no
|
||||
* host CLI ever reads and that disappears with the container. This guard turns
|
||||
* that silent no-op into an actionable refusal.
|
||||
*
|
||||
* Bind-mounted targets (the compose `host` profile) are allowed through: the
|
||||
* mount is the operator's explicit statement that the path reaches the host.
|
||||
*/
|
||||
|
||||
const TRUE_VALUES = new Set(["1", "true", "yes", "on"]);
|
||||
|
||||
/** Exit code for a refused write — matches the CLI's usage-error convention. */
|
||||
export const CONTAINER_WRITE_EXIT_CODE = 2;
|
||||
|
||||
function envAllowsContainerWrite(env = process.env) {
|
||||
return TRUE_VALUES.has(
|
||||
String(env.OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE ?? "")
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Classify a pending config write.
|
||||
*
|
||||
* @param {string} targetPath Absolute path the command is about to write.
|
||||
* @param {{
|
||||
* toolLabel?: string,
|
||||
* hostCommand?: string,
|
||||
* allowContainerWrite?: boolean,
|
||||
* dryRun?: boolean,
|
||||
* env?: NodeJS.ProcessEnv,
|
||||
* deps?: object,
|
||||
* }} options
|
||||
* @returns {Promise<{ok: boolean, message?: string, warning?: string}>}
|
||||
*/
|
||||
export async function assertHostConfigTarget(targetPath, options = {}) {
|
||||
const {
|
||||
toolLabel,
|
||||
hostCommand,
|
||||
allowContainerWrite = false,
|
||||
dryRun = false,
|
||||
env = process.env,
|
||||
deps,
|
||||
} = options;
|
||||
|
||||
let describeContainerTarget;
|
||||
let buildContainerWriteRefusal;
|
||||
let CLI_OVERRIDE_HINT;
|
||||
try {
|
||||
// `.ts` extension is required so the published package (which ships only TS
|
||||
// source, resolved through tsx) can load these. See #2509.
|
||||
({ describeContainerTarget } = await import("../../../src/shared/utils/containerEnv.ts"));
|
||||
({ buildContainerWriteRefusal, CLI_OVERRIDE_HINT } =
|
||||
await import("../../../src/shared/utils/containerConfigGuard.ts"));
|
||||
} catch {
|
||||
// Fail open: a guard that cannot load must not block a legitimate host run.
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
const info = describeContainerTarget(targetPath, deps);
|
||||
if (!info.ephemeral) return { ok: true };
|
||||
|
||||
if (dryRun) {
|
||||
return {
|
||||
ok: true,
|
||||
warning:
|
||||
`[dry-run] ${targetPath} is inside the container and is not mounted from the host — ` +
|
||||
`a real run would be refused. See --allow-container-write.`,
|
||||
};
|
||||
}
|
||||
|
||||
if (allowContainerWrite || envAllowsContainerWrite(env)) {
|
||||
return {
|
||||
ok: true,
|
||||
warning:
|
||||
`Writing to ${targetPath} inside the container as requested — this file is lost when ` +
|
||||
`the container is recreated and host CLIs will not see it.`,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
ok: false,
|
||||
message: buildContainerWriteRefusal(targetPath, {
|
||||
toolLabel,
|
||||
hostCommand,
|
||||
overrideHint: CLI_OVERRIDE_HINT,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Container check for commands that write nothing but still print host-oriented
|
||||
* instructions (setup-cursor). Fails closed to `false` so a broken import never
|
||||
* turns into a spurious warning.
|
||||
*/
|
||||
export async function isContainerRuntime(deps) {
|
||||
try {
|
||||
const { isRunningInContainer } = await import("../../../src/shared/utils/containerEnv.ts");
|
||||
return isRunningInContainer(deps);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Guard + report. Returns 0 to continue, or CONTAINER_WRITE_EXIT_CODE when the
|
||||
* caller should abort and return that code.
|
||||
*/
|
||||
export async function guardHostConfigTarget(targetPath, options = {}) {
|
||||
const result = await assertHostConfigTarget(targetPath, options);
|
||||
if (result.warning) printInfo(result.warning);
|
||||
if (result.ok) return 0;
|
||||
printError(result.message);
|
||||
return CONTAINER_WRITE_EXIT_CODE;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
- **feat(cli):** container-aware auto-config — `setup-*`, `omniroute configure`, `omniroute config set` and the CLI-tool config APIs now refuse to write into a containerised OmniRoute's ephemeral home (CLI exits `2`, API returns `422` with `containerEphemeralTarget`) and point at the host-CLI or bind-mount setup instead; `--allow-container-write` / `OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE=true` opt back in. Also fixes `CLI_CONFIG_HOME` so the Compose `host` profile's `/host-home` bind mounts are honoured instead of silently falling back to the container home. (#10057)
|
||||
@@ -1 +0,0 @@
|
||||
- feat(modality-bridge): bridge Chat and Responses video parts through a strict trusted-loopback, quota-bounded FFmpeg broker; enforce HTTPS redirects/SSRF plus format, protocol, stream, pixel, frame, 50 MiB broker/remote, 36 MiB inline, and 120-second limits; propagate caller aborts; preserve the actual successful fallback model through cache/meta/headers; expose sampled latency and honest success telemetry; and ship the localized Video settings UI (#9760)
|
||||
@@ -1 +0,0 @@
|
||||
- **feat(radar):** Persist local model display-name/enabled overrides and hide/restore tombstones, with authenticated catalog controls and feed safety precedence ([#9830](https://github.com/diegosouzapw/OmniRoute/pull/9830))
|
||||
@@ -1 +0,0 @@
|
||||
- **feat(radar):** add curated-family combo suggestions, a guided combo page, and the read-only Radar MCP catalog tool ([#9836](https://github.com/diegosouzapw/OmniRoute/pull/9836))
|
||||
@@ -1 +0,0 @@
|
||||
- **feat(radar):** add a signed live offers feed and supporter offers dashboard ([#9912](https://github.com/diegosouzapw/OmniRoute/pull/9912))
|
||||
@@ -1 +0,0 @@
|
||||
- **feat(radar):** add signed Intel insights, supporter recognition, and local Radar CLI commands ([#9923](https://github.com/diegosouzapw/OmniRoute/pull/9923))
|
||||
@@ -1 +0,0 @@
|
||||
- **feat(radar):** add a localized public news feed and dismissible dashboard launch banner, with the Radar announcement staged inactive for a separately authorized launch ([#9926](https://github.com/diegosouzapw/OmniRoute/pull/9926))
|
||||
1
changelog.d/fixes/10096-kimi-coding-apikey-save.md
Normal file
@@ -0,0 +1 @@
|
||||
- fix(dashboard): remap unified Kimi Code card API-key save to the admitted `kimi-coding-apikey` connection id, fixing 400 "Invalid provider" on Save (#10096)
|
||||
@@ -1 +0,0 @@
|
||||
- **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))
|
||||
@@ -1 +0,0 @@
|
||||
- **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))
|
||||
@@ -1 +0,0 @@
|
||||
- **fix(providers):** preserve validator HTTP status codes in API-key and web connection-test results so callers can distinguish authentication, rate-limit, and upstream failures ([#10272](https://github.com/diegosouzapw/OmniRoute/pull/10272)) — thanks @Zartharas
|
||||
@@ -1 +0,0 @@
|
||||
- **fix(sse):** tiny-budget reasoning probes (e.g. Claude Code's `/model` check sends `max_tokens: 1`) are answered with a valid truncated 200 instead of relaying the upstream 5xx "empty response content" — which previously also marked the connection unavailable and poisoned fallback/cooldown bookkeeping for a request that is only a probe ([#10281](https://github.com/diegosouzapw/OmniRoute/issues/10281)) — thanks @harkaranbrar7
|
||||
@@ -1 +0,0 @@
|
||||
- **fix(chat-body-admission):** restore a single process-wide admission budget — heavyweight leases and queued bytes are now bounded once for the whole process instead of per session, so one session can no longer mint extra capacity or starve others; per-session fairness is preserved via round-robin dispatch ([#10110](https://github.com/diegosouzapw/OmniRoute/issues/10110))
|
||||
@@ -1 +0,0 @@
|
||||
- **fix(providers):** validate Z.ai web Local Storage sessions against the authenticated user-settings endpoint and preserve exact upstream status codes ([#10329](https://github.com/diegosouzapw/OmniRoute/pull/10329)) — thanks @Zartharas
|
||||
@@ -1 +0,0 @@
|
||||
- **fix(db):** `getSettings()` defaults `debugMode` to `false` — fresh installs no longer run in debug mode (persisted `debugMode: true` is preserved) ([#10372](https://github.com/diegosouzapw/OmniRoute/pull/10372) — thanks @lamchun1110)
|
||||
@@ -1 +0,0 @@
|
||||
- **fix(executors):** OpencodeExecutor and MimocodeExecutor now rotate to the next account on network exceptions (timeout, connection refused/reset) when the failed account has a dedicated proxy, not only on 429 — a throw on one account no longer fails the whole request when other accounts remain. Accounts sharing the default egress (no proxy) fail fast instead of retrying the same outage against every account. The shared rotation mechanics (`pickAccount`/`markCooldown`/`markSuccess`) are now extracted into `accountRotation.ts`, fixing an identical unconditional-cooldown gap that pre-dated this PR in MimocodeExecutor ([#10393](https://github.com/diegosouzapw/OmniRoute/pull/10393))
|
||||
@@ -1 +0,0 @@
|
||||
- **fix(sse):** the header-budget drop warning fires once per unique dropped-header set instead of on every SSE response (warn-storm fix) ([#10397](https://github.com/diegosouzapw/OmniRoute/pull/10397) — thanks @lamchun1110)
|
||||
@@ -1 +0,0 @@
|
||||
- **fix(guardrails):** Vision Bridge now reroutes whole requests for named combos whose targets have zero vision-capable models (previously such image requests died with `capability_mismatch` when the describe path could not run), and when the fallback describe path also fails for every image the request degrades to explicit `(unavailable)` stub text instead of preserving images the combo cannot consume ([#10415](https://github.com/diegosouzapw/OmniRoute/pull/10415)) — thanks @rqzbeh
|
||||
@@ -1,2 +0,0 @@
|
||||
- **fix(antigravity):** geo-blocked egress (Google "User location is not supported") is now classified (scoped to the Google AI surfaces that emit it: Cloud Code/Gemini Code Assist, Gemini API, Vertex), cached as a 24h per-account exclusion so routing continues with other accounts, and surfaced with an actionable message; the dashboard connection test now probes the real `streamGenerateContent` model surface instead of the non-geo-restricted OAuth userinfo endpoint ([#10420](https://github.com/diegosouzapw/OmniRoute/pull/10420)) — thanks @rqzbeh
|
||||
- **fix(antigravity):** strip competing-agent identity sentences from system prompts (e.g. "You are a Claude agent, built on Anthropic's Claude Agent SDK.") that Antigravity flags and answers with 429 RESOURCE_EXHAUSTED (port of decolua/9router b566b20) ([#10420](https://github.com/diegosouzapw/OmniRoute/pull/10420)) — thanks @rqzbeh
|
||||
@@ -1 +0,0 @@
|
||||
- **fix(usage):** read Gemini `usageMetadata` out of the antigravity `{ response: {...} }` envelope so non-streaming requests log real token usage instead of `IN 0 | OUT 0` (port of decolua/9router#59d858b) ([#10430](https://github.com/diegosouzapw/OmniRoute/pull/10430)) — thanks @rqzbeh
|
||||
@@ -1 +0,0 @@
|
||||
- fix(ci): make `Build (advisory)` produce a signal again — pinned to a hosted runner with the swap/heap provisioning `Fast Production Build` proves sufficient, and scoped to fork PRs, which are the only ones `build.yml` cannot cover (72 of the last 100 PRs into `release/**`)
|
||||
@@ -1 +0,0 @@
|
||||
- **fix(ops):** Docker HEALTHCHECK probes lightweight `/healthz` instead of `/api/monitoring/health` so a busy event loop does not mark the container Unhealthy (`scripts/dev/healthcheck.mjs`)
|
||||
@@ -1 +0,0 @@
|
||||
- **fix(db):** the sql.js fallback now publishes the database atomically — temp file in the same directory, `fsync`, then `rename()` — instead of rewriting it in place with `writeFileSync`. sql.js has no incremental write path, so every save rewrote the whole image through an `O_TRUNC` open: for the duration of the write the on-disk database was 0 bytes and then partial, a window that scales with database size and recurs on every save. Unlike better-sqlite3 / node:sqlite, that window is not covered by SQLite's locking protocol, so it was visible to every OTHER process reading the same file (a backup job, a metrics exporter, an operator running `sqlite3`), which got `SQLITE_CORRUPT` — "database disk image is malformed" — while `PRAGMA integrity_check` passed moments later. It also closes a total-loss window: a crash mid-write used to leave the real database truncated, and now only leaves a stale temp file
|
||||
@@ -1 +0,0 @@
|
||||
- **docs(ops):** document Kubernetes probe recommendations — TCP (or soft HTTP) liveness, HTTP `/healthz` readiness, avoid `/api/monitoring/health` as kubelet liveness ([#10297](https://github.com/diegosouzapw/OmniRoute/pull/10297)) — thanks @RaviTharuma
|
||||
@@ -27,7 +27,6 @@
|
||||
"providers-bailian-coding-plan.spec.ts": 240,
|
||||
"providers-management.spec.ts": 324,
|
||||
"proxy-registry.smoke.spec.ts": 218,
|
||||
"radar-guided-setup.spec.ts": 177,
|
||||
"resilience-plan-alignment.spec.ts": 382,
|
||||
"responsive.spec.ts": 21,
|
||||
"search-tools-studio.spec.ts": 133,
|
||||
@@ -37,4 +36,4 @@
|
||||
"traffic-inspector.spec.ts": 212,
|
||||
"translator-friendly.spec.ts": 115,
|
||||
"visual-resilience-smoke.spec.ts": 20
|
||||
}
|
||||
}
|
||||
@@ -205,10 +205,10 @@ Runs on pull requests only.
|
||||
|
||||
Runs after `build`. Blocks merge on failure.
|
||||
|
||||
| Suite | Validates | Blocking |
|
||||
| ---------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| `test:vitest` | MCP server (109 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 |
|
||||
| Suite | Validates | Blocking |
|
||||
| ---------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| `test:vitest` | MCP server (105 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)
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ OmniRoute/
|
||||
| **.gitleaks.toml** | gitleaks secret-scan ruleset |
|
||||
| **.zizmor.yml** | zizmor GitHub-Actions security-lint config |
|
||||
| **socket.yml** | Socket.dev supply-chain config |
|
||||
| **news.json** | Localized v2 announcement feed; Radar launch item ships inactive |
|
||||
| **news.json** | In-app release-notes feed (read by `src/shared/utils/releaseNotes.ts`) |
|
||||
| **flake.nix** / **flake.lock** | Nix dev-shell definition + lock |
|
||||
| **.env** | Local secrets (gitignored — generated from `.env.example`) |
|
||||
|
||||
@@ -182,7 +182,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/` | 95+ domain DB modules + 144 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.) |
|
||||
@@ -196,7 +196,7 @@ src/
|
||||
| `memory/vectorStore.ts` | sqlite-vec v0.1.9 wrapper — KNN brute-force + hybrid RRF (FTS5 + vector, k=60). Lazy-init, degrades gracefully when sqlite-vec unavailable. (plan 21) |
|
||||
| `memory/reindex.ts` | `runReindexBatch()` — processes memories with `needs_reindex=1` in background; called by `POST /api/memory/reindex` and lazy-backfill path. (plan 21) |
|
||||
| `monitoring/` | Health checks, metrics emission |
|
||||
| `oauth/` | OAuth/import flows for 22 provider modules (agy, antigravity, claude, cline, codebuddy-cn, codex, cursor, devin-desktop, ghe-copilot, github, gitlab-duo, grok-cli-oauth, grok-cli, kilocode, kimi-coding, kiro, qoder, raycast, trae, xai-oauth, zed-hosted, zed) |
|
||||
| `oauth/` | OAuth/import flows for 22 provider modules (agy, antigravity, claude, cline, codebuddy-cn, codex, cursor, devin-desktop, ghe-copilot, github, gitlab-duo, grok-cli-oauth, grok-cli, kilocode, kimi-coding, kiro, qoder, raycast, trae, xai-oauth, zed-hosted, zed) |
|
||||
| `plugins/` | Plugin registry |
|
||||
| `promptCache/` | Anthropic-style prompt cache breakpoints |
|
||||
| `skills/` | Skills framework (built-in + marketplace + SkillsSH) — see `docs/frameworks/SKILLS.md` |
|
||||
@@ -209,7 +209,7 @@ src/
|
||||
| `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/db/` — Database (117 modules + 144 migrations)
|
||||
|
||||
| Subdir | Purpose |
|
||||
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
@@ -256,7 +256,6 @@ src/
|
||||
| `utils/circuitBreaker.ts` | Provider circuit breaker (see `docs/architecture/RESILIENCE_GUIDE.md`) |
|
||||
| `utils/apiAuth.ts` | API key validation, scope checking |
|
||||
| `utils/fetchTimeout.ts` | Timeout/abort wrappers for upstream fetch |
|
||||
| `utils/releaseNotes.ts` | Closed v2/legacy announcement parser, localization and ID dismissal |
|
||||
|
||||
---
|
||||
|
||||
@@ -271,7 +270,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 (105 tools, 3 transports, 31 scopes)
|
||||
├── config/ # Provider/model registries, header config, model aliases
|
||||
├── utils/ # TLS client, proxy fetch/dispatcher, network helpers
|
||||
├── index.ts # Workspace entry
|
||||
@@ -407,7 +406,7 @@ open-sse/
|
||||
|
||||
| Doc | Purpose |
|
||||
| -------------------------- | ------------------------------------------------------------------- |
|
||||
| `MCP-SERVER.md` | MCP server: 109 tools, 3 transports, 33 scopes, REST endpoints |
|
||||
| `MCP-SERVER.md` | MCP server: 105 tools, 3 transports, 31 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 |
|
||||
|
||||
@@ -330,75 +330,32 @@ excludeMarkers, defaultRetryAfterMs}`), matched via `applyStatusRestatement()`.
|
||||
|
||||
Permanent errors (agentrouter's `无权访问模型` — no access to this model) are
|
||||
NEVER restated: `excludeMarkers` vetoes the rule even when `textMarkers` hit,
|
||||
so the error keeps its original status and nothing retries it forever. The
|
||||
matching provider classification rule
|
||||
(`agentrouter-model-access-denied` in `open-sse/config/providerErrorRules.ts`:
|
||||
`reason: "auth_error"`, `scope: "model"`, a `6h` declared base cooldown) is
|
||||
consulted by `checkFallbackError` (`open-sse/services/accountFallback.ts`)
|
||||
*before* the generic apikey-category `FORBIDDEN` early-return, gated on
|
||||
`honorsRuleLockScope(provider)` (#10334 — currently agentrouter-exclusive via
|
||||
the `HONORS_RULE_LOCK_SCOPE_PROVIDERS` allowlist in
|
||||
`providerErrorRules.ts`). The rule's declared 6h cooldown flows through as
|
||||
`fallbackResult.baseCooldownMs`, but it still feeds the pre-existing
|
||||
per-model-quota lockout path (`lockModelIfPerModelQuota()` /
|
||||
`recordModelLockoutFailure()`, unchanged by #10334 except for the cooldown
|
||||
source): it is clamped down to the operator's `mlSettings.maxCooldownMs`
|
||||
(default `1_800_000ms` / 30min), like every other model lockout, and the
|
||||
*persisted lockout reason* stays the pre-existing hardcoded `"forbidden"`,
|
||||
not the rule's `"auth_error"` — only the cooldown duration is honored
|
||||
end-to-end, not the reason string. The connection itself stays active;
|
||||
sibling models on the same connection are unaffected.
|
||||
so the error keeps its original status and nothing retries it forever. A
|
||||
separate provider classification rule
|
||||
(`agentrouter-model-access-denied` in `open-sse/config/providerErrorRules.ts`)
|
||||
declares an `auth_error`/scope-`model` match for this text, but it does not
|
||||
fire on the live production path today: the rule only matches `status ===
|
||||
403`, and `checkFallbackError`'s apikey-category `FORBIDDEN` branch
|
||||
(`open-sse/services/accountFallback.ts`) returns early for a plain 403
|
||||
*before* the provider-rule lookup ever runs. In practice a `无权访问模型` 403
|
||||
is handled the same way as the base apikey-provider 403 path (see Connection
|
||||
Cooldown, §2), not as a 6h model lockout. The rule still exists as a
|
||||
declarative classification consumable by future callers of `classifyError`
|
||||
with context — wiring it into the production `checkFallbackError` path is
|
||||
tracked as a follow-up, not yet done.
|
||||
|
||||
Restated quota errors (`额度不足`) reach a provider rule in production
|
||||
(`agentrouter-user-quota-exhausted`: `reason: "quota_exhausted"`, `scope:
|
||||
"connection"`, no declared cooldown of its own — the persistence layer's
|
||||
scaled backoff default applies). Since #10334, `scope` on
|
||||
`ProviderErrorRuleMatch` IS consumed end-to-end, but **only** for providers in
|
||||
the `HONORS_RULE_LOCK_SCOPE_PROVIDERS` allowlist (`providerErrorRules.ts` —
|
||||
today only `"agentrouter"`, gated via `honorsRuleLockScope()`). For every
|
||||
other provider `scope` remains informational, exactly as before #10334.
|
||||
`checkFallbackError` surfaces the matched rule's scope as
|
||||
`fallbackResult.ruleScope`; `isAgentrouterConnectionQuotaScope()`
|
||||
(`src/sse/services/auth.ts`) is the shared guard that confirms a
|
||||
`ruleScope` is genuinely safe to honor as a connection-wide, self-recovering
|
||||
signal (scope `"connection"`, reason `quota_exhausted`, never `permanent`,
|
||||
never `creditsExhausted` — a defense against a future rule pairing scope
|
||||
`"connection"` with a permanent account state). Two consumers call it:
|
||||
|
||||
- **Persistence** (`markAccountUnavailable()`, `src/sse/services/auth.ts`):
|
||||
instead of falling into the passthrough-provider **per-model** lockout
|
||||
branch (agentrouter is `passthroughModels: true` → `hasPerModelQuota()`
|
||||
returns `true`), it applies a **temporary connection cooldown** —
|
||||
`testStatus: "unavailable"` + `rateLimitedUntil`, never a terminal status
|
||||
(`credits_exhausted`/`banned`/`expired`) — so the connection self-recovers
|
||||
once the cooldown lapses instead of requiring a manual credential reset.
|
||||
Skipped for connections with `disableCooling: true` (#2997): that opt-out
|
||||
falls through to the per-model lockout instead (a documented trade-off —
|
||||
see the code comment above the branch).
|
||||
- **Same-request combo routing** (`applyComboTargetExhaustion()`,
|
||||
`open-sse/services/combo/targetExhaustion.ts`): the same guard marks the
|
||||
connection into the in-memory `exhaustedConnections` set, keyed
|
||||
`${provider}:${connectionId}`. This only skips a remaining SAME-REQUEST
|
||||
target that *itself already carries that exact `connectionId`* on its own
|
||||
target object (`getExhaustedTargetSkipReason()`,
|
||||
`open-sse/services/combo/comboPredicates.ts`, `if (provider &&
|
||||
connectionId)` before the `exhaustedConnections` lookup) — a plain
|
||||
model-list combo, where sibling targets carry no pinned `connectionId` of
|
||||
their own and one is only resolved per-dispatch from the response's
|
||||
`X-OmniRoute-Selected-Connection-Id` header, never hits that key match. For
|
||||
that common case, the real protection against a remaining leg reusing the
|
||||
just-exhausted account is NOT this Set — it is the persistence layer above
|
||||
(the connection's `rateLimitedUntil` is now in the future) combined with
|
||||
this same guard suppressing `transientRateLimitedProviders` for the
|
||||
failure (see "Two-stage design" and the code comment on the
|
||||
`isAgentrouterConnectionQuotaScope` branch in `targetExhaustion.ts`): with
|
||||
that Set left unmarked, `combo.ts`'s `allowRateLimitedConnection` force-allow
|
||||
(`open-sse/services/combo.ts:1005-1013`, `:2734-2738`) does NOT kick in for
|
||||
the provider's remaining legs, so credential selection's `rateLimitedUntil`
|
||||
filter (`src/sse/services/auth.ts:1238`) is honored normally and a
|
||||
remaining leg either picks a different, still-eligible agentrouter
|
||||
connection or fails with no credentials available — it does not force its
|
||||
way back onto the connection this branch just cooled down.
|
||||
Restated quota errors (`额度不足`) do reach a provider rule in production
|
||||
(`agentrouter-user-quota-exhausted`, scope `"connection"`), but `scope` on
|
||||
`ProviderErrorRuleMatch` is currently informational — the persistence path
|
||||
(`checkFallbackError` → `combo.ts`) only consumes `reason` and `cooldownMs`,
|
||||
never `scope`. What actually happens for agentrouter (`passthroughModels:
|
||||
true` → `hasPerModelQuota()` returns `true`) is a **per-model** lockout via
|
||||
`recordModelLockoutFailure()`: the connection itself is never cooled down for
|
||||
this error (`combo.ts` skips `recordProviderCooldown` for 429 when
|
||||
`hasPerModelQuota` is true), so other models on the same account keep being
|
||||
tried — each one burns one call and its own lockout before combo routing
|
||||
moves on. Honoring `scope` end-to-end (so a `"connection"` match actually
|
||||
locks the connection) is tracked as a follow-up.
|
||||
|
||||
### Two-stage design: status restatement, then classification
|
||||
|
||||
@@ -423,15 +380,6 @@ allowlisted providers, the structured error otherwise. Adding a provider to
|
||||
that the default path for every provider not on the list stays
|
||||
byte-for-byte unchanged.
|
||||
|
||||
A rule's `scope` (`model` / `provider` / `connection`) is a separate opt-in
|
||||
from `FULL_TEXT_RULE_PROVIDERS`: `checkFallbackError` only surfaces it as
|
||||
`fallbackResult.ruleScope`, and downstream consumers only honor it as
|
||||
anything other than an informational label, for providers in the
|
||||
`HONORS_RULE_LOCK_SCOPE_PROVIDERS` allowlist in the same file (`gated via
|
||||
honorsRuleLockScope()` — today only `"agentrouter"`). See "Restated quota
|
||||
errors" above for what a `scope: "connection"` match actually does once a
|
||||
provider is on that allowlist.
|
||||
|
||||
### Adding a new quota-misstating gateway
|
||||
|
||||
1. Register one rule array in `statusRestatementRegistry`
|
||||
@@ -447,15 +395,7 @@ provider is on that allowlist.
|
||||
`checkFallbackError` only ever hands the rule the structured
|
||||
`{code, type}` error and a body-text rule will never match live traffic.
|
||||
Rules that match purely on `status`/`headers` (like Opencode's or
|
||||
Minimax's) do not need this opt-in. Separately, if the rule declares
|
||||
`scope: "connection"` and the intent is an actual connection-wide cooldown
|
||||
plus same-request combo skip (not just an informational label), add the
|
||||
provider id to `HONORS_RULE_LOCK_SCOPE_PROVIDERS` in the same file — this
|
||||
is what gates `isAgentrouterConnectionQuotaScope()`-style consumption in
|
||||
`markAccountUnavailable()` (`src/sse/services/auth.ts`) and
|
||||
`applyComboTargetExhaustion()`
|
||||
(`open-sse/services/combo/targetExhaustion.ts`); without it, `scope`
|
||||
still flows through `fallbackResult.ruleScope` but nothing acts on it.
|
||||
Minimax's) do not need this opt-in.
|
||||
3. Add unit tests mirroring `tests/unit/upstream-status-restatement.test.ts`
|
||||
and `tests/unit/agentrouter-error-rules.test.ts` (including the
|
||||
not-permanent / not-creditsExhausted guards, and — if the provider needs
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<svg viewBox="0 0 1200 350" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Animated terminal demoing the OmniRoute CLI: omniroute providers list (340 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 the 80+ command surface: 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 (339 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 the 80+ command surface: 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.345;0.351;0.357;0.363;0.369;0.375;0.381;0.387;1" dur="18s" repeatCount="indefinite"/></rect></clipPath><clipPath id="tw2"><rect x="64" y="46" height="26" width="0"><animate attributeName="width" calcMode="discrete" values="0;20;41;61;82;102;122;143;163;163" keyTimes="0;0.678;0.684;0.690;0.696;0.702;0.708;0.714;0.720;1" dur="18s" repeatCount="indefinite"/></rect></clipPath></defs>
|
||||
<rect width="1200" height="350" fill="#0d1117"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@@ -1,4 +1,4 @@
|
||||
<svg viewBox="0 0 1200 780" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Comparison table: OmniRoute versus 9router, OpenRouter, CLIProxyAPI and LiteLLM across 13 capabilities. OmniRoute is the only one with the full set: 340 providers, 90+ free providers built-in, 19 routing strategies, 12-engine token compression, a built-in MCP server with 109 tools, A2A protocol, persistent memory, guardrails, cloud agents, TLS fingerprint stealth, desktop/Termux/PWA, 43 UI locales and 100% MIT self-hosted. 9router has free providers, RTK compression and translation but no MCP, A2A, memory, guardrails, cloud agents or stealth. OpenRouter is a hosted SaaS with 400+ models, guardrails and a hosted MCP but is not self-hosted and lacks A2A, memory, cloud agents and stealth. CLIProxyAPI is a light OAuth proxy with two routing strategies. LiteLLM has 100+ providers, A2A and extensive guardrails but no memory, compression, free tier, stealth or cloud agents.">
|
||||
<svg viewBox="0 0 1200 780" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Comparison table: OmniRoute versus 9router, OpenRouter, CLIProxyAPI and LiteLLM across 13 capabilities. OmniRoute is the only one with the full set: 339 providers, 90+ free providers built-in, 19 routing strategies, 12-engine token compression, a built-in MCP server with 105 tools, A2A protocol, persistent memory, guardrails, cloud agents, TLS fingerprint stealth, desktop/Termux/PWA, 43 UI locales and 100% MIT self-hosted. 9router has free providers, RTK compression and translation but no MCP, A2A, memory, guardrails, cloud agents or stealth. OpenRouter is a hosted SaaS with 400+ models, guardrails and a hosted MCP but is not self-hosted and lacks A2A, memory, cloud agents and stealth. CLIProxyAPI is a light OAuth proxy with two routing strategies. LiteLLM has 100+ providers, A2A and extensive guardrails but no memory, compression, free tier, stealth or cloud agents.">
|
||||
<desc>Static-header comparison table where each capability row fades in top to bottom; the OmniRoute column is highlighted and shows a check or a leading value in every row, while competitors show a mix of checks, partials and crosses.</desc>
|
||||
<defs>
|
||||
<pattern id="gC" width="32" height="32" patternUnits="userSpaceOnUse"><path d="M 32 0 L 0 0 0 32" fill="none" stroke="#ffffff" stroke-opacity="0.05" stroke-width="1"/></pattern>
|
||||
@@ -57,7 +57,7 @@
|
||||
</g>
|
||||
<g opacity="0"><animate attributeName="opacity" values="0;1" dur="0.4s" begin="0.51s" fill="freeze"/>
|
||||
<text x="44" y="364" font-size="14.5" fill="#c9d1d9">Built-in MCP server (own tools)</text>
|
||||
<text x="440" y="364" text-anchor="middle" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="15" font-weight="800" fill="#7ee787">109</text>
|
||||
<text x="440" y="364" text-anchor="middle" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="15" font-weight="800" fill="#7ee787">105</text>
|
||||
<use href="#no" x="604" y="359"/>
|
||||
<use href="#mid" x="760" y="359"/>
|
||||
<use href="#no" x="916" y="359"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
@@ -1,4 +1,4 @@
|
||||
<svg viewBox="0 0 1200 540" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="The OmniRoute promise: one endpoint, 340 providers — never stop building, OmniRoute picks the cheapest one that works. Six pillars. Never hit limits: auto-fallback across 340 providers in milliseconds, quota out means the next provider takes over with zero downtime. Save up to 95 percent of tokens: RTK plus Caveman stacked compression cuts 15 to 95 percent of eligible tokens, about 89 percent average on tool-heavy sessions. Zero dollars to start: 90+ providers with a free tier, 56 free forever — Qoder, Pollinations, Cloudflare, SiliconFlow — no card needed. Every tool works: 33 coding agents including Claude Code, Codex, Cursor, Cline, Copilot and Antigravity through one config. One endpoint: OpenAI, Claude, Gemini and Responses API translation — point any tool at /v1 and it just works. Production-grade: circuit breakers, TLS stealth, MCP with 109 tools, A2A, memory, guardrails, evals — 25,000+ tests.">
|
||||
<svg viewBox="0 0 1200 540" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="The OmniRoute promise: one endpoint, 339 providers — never stop building, OmniRoute picks the cheapest one that works. Six pillars. Never hit limits: auto-fallback across 339 providers in milliseconds, quota out means the next provider takes over with zero downtime. Save up to 95 percent of tokens: RTK plus Caveman stacked compression cuts 15 to 95 percent of eligible tokens, about 89 percent average on tool-heavy sessions. Zero dollars to start: 90+ providers with a free tier, 40+ free forever — Qoder, Pollinations, Cloudflare, SiliconFlow — no card needed. Every tool works: 33 coding agents including Claude Code, Codex, Cursor, Cline, Copilot and Antigravity through one config. One endpoint: OpenAI, Claude, Gemini and Responses API translation — point any tool at /v1 and it just works. Production-grade: circuit breakers, TLS stealth, MCP with 105 tools, A2A, memory, guardrails, evals — 25,000+ tests.">
|
||||
<desc>Animated promise card: six pillar tiles fade in in reading order, then a soft colored border highlight sweeps from tile to tile in a continuous cycle.</desc>
|
||||
<defs>
|
||||
<pattern id="gridPaperP" width="32" height="32" patternUnits="userSpaceOnUse">
|
||||
@@ -21,7 +21,7 @@
|
||||
<line x1="150" y1="53" x2="1160" y2="53" stroke="#232b38" stroke-width="1.5"/>
|
||||
</g>
|
||||
<g>
|
||||
<text x="40" y="100" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="23" font-weight="600" fill="#c9d1d9">One endpoint. <tspan fill="#a78bfa" font-weight="800">340 providers.</tspan> Never stop building — OmniRoute picks <tspan fill="#7ee787" font-weight="700">the cheapest one that works</tspan>.</text>
|
||||
<text x="40" y="100" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="23" font-weight="600" fill="#c9d1d9">One endpoint. <tspan fill="#a78bfa" font-weight="800">339 providers.</tspan> Never stop building — OmniRoute picks <tspan fill="#7ee787" font-weight="700">the cheapest one that works</tspan>.</text>
|
||||
</g>
|
||||
|
||||
<g font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif">
|
||||
@@ -38,7 +38,7 @@
|
||||
<line x1="3.9" y1="3.9" x2="18.1" y2="18.1"/>
|
||||
</g>
|
||||
<text x="102" y="170" font-size="18" font-weight="800" fill="#74b9ff">Never hit limits</text>
|
||||
<text x="66" y="204" font-size="13.5" fill="#a1a1aa">Auto-fallback across 340 providers in</text>
|
||||
<text x="66" y="204" font-size="13.5" fill="#a1a1aa">Auto-fallback across 339 providers in</text>
|
||||
<text x="66" y="226" font-size="13.5" fill="#a1a1aa">milliseconds. Quota out? The next provider</text>
|
||||
<text x="66" y="248" font-size="13.5" fill="#a1a1aa">takes over — zero downtime.</text>
|
||||
</g>
|
||||
@@ -73,7 +73,7 @@
|
||||
<circle cx="6.6" cy="6.6" r="1.4" fill="#fdcb6e" stroke="none"/>
|
||||
</g>
|
||||
<text x="862" y="170" font-size="18" font-weight="800" fill="#fdcb6e">$0 to start</text>
|
||||
<text x="826" y="204" font-size="13.5" fill="#a1a1aa">90+ providers with a free tier, 56 free</text>
|
||||
<text x="826" y="204" font-size="13.5" fill="#a1a1aa">90+ providers with a free tier, 40+ free</text>
|
||||
<text x="826" y="226" font-size="13.5" fill="#a1a1aa">forever — Qoder, Pollinations, Cloudflare,</text>
|
||||
<text x="826" y="248" font-size="13.5" fill="#a1a1aa">SiliconFlow… No card needed.</text>
|
||||
</g>
|
||||
@@ -125,7 +125,7 @@
|
||||
<path d="M 7,11 L 10,14 L 15.4,8.2"/>
|
||||
</g>
|
||||
<text x="862" y="354" font-size="18" font-weight="800" fill="#7ee787">Production-grade</text>
|
||||
<text x="826" y="388" font-size="13.5" fill="#a1a1aa">Circuit breakers, TLS stealth, MCP (109</text>
|
||||
<text x="826" y="388" font-size="13.5" fill="#a1a1aa">Circuit breakers, TLS stealth, MCP (105</text>
|
||||
<text x="826" y="410" font-size="13.5" fill="#a1a1aa">tools), A2A, memory, guardrails, evals —</text>
|
||||
<text x="826" y="432" font-size="13.5" fill="#a1a1aa">25,000+ tests.</text>
|
||||
</g>
|
||||
|
||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
@@ -1,4 +1,4 @@
|
||||
<svg viewBox="0 0 1200 548" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="OmniRoute hero: Never stop coding. Every AI tool to 340 providers — 90+ free — through one endpoint. Claude Code, Codex, Cursor, Cline, Copilot and Antigravity into free Claude, GPT and Gemini with auto-fallback. RTK + Caveman stacked compression saves 15 to 95 percent of tokens — about 89 percent average on tool-heavy sessions — so you never hit limits. Stats: 340 AI providers, 90+ free tiers, about 1.51B free tokens per month, 15 to 95 percent token savings, 19 routing strategies, zero dollars to start.">
|
||||
<svg viewBox="0 0 1200 548" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="OmniRoute hero: Never stop coding. Every AI tool to 339 providers — 90+ free — through one endpoint. Claude Code, Codex, Cursor, Cline, Copilot and Antigravity into free Claude, GPT and Gemini with auto-fallback. RTK + Caveman stacked compression saves 15 to 95 percent of tokens — about 89 percent average on tool-heavy sessions — so you never hit limits. Stats: 339 AI providers, 90+ free tiers, about 1.51B free tokens per month, 15 to 95 percent token savings, 19 routing strategies, zero dollars to start.">
|
||||
<desc>Animated hero card: a pulse travels the divider line and a compression bar demo repeatedly shrinks a prompt by up to 95 percent; all headline content is static and readable on the first frame.</desc>
|
||||
<defs>
|
||||
<pattern id="gridPaperH" width="32" height="32" patternUnits="userSpaceOnUse">
|
||||
@@ -28,7 +28,7 @@
|
||||
<text x="48" y="138" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="60" font-weight="800" fill="#e9edf3">Never stop coding<tspan fill="#a855f7">.</tspan></text>
|
||||
|
||||
<!-- subheadline -->
|
||||
<text x="48" y="184" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="25" font-weight="600" fill="#c9d1d9">Every AI tool → <tspan fill="#a78bfa" font-weight="800">340 providers</tspan> — <tspan fill="#7ee787" font-weight="800">90+ free</tspan> — through one endpoint.</text>
|
||||
<text x="48" y="184" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="25" font-weight="600" fill="#c9d1d9">Every AI tool → <tspan fill="#a78bfa" font-weight="800">339 providers</tspan> — <tspan fill="#7ee787" font-weight="800">90+ free</tspan> — through one endpoint.</text>
|
||||
|
||||
<!-- plug line -->
|
||||
<text x="48" y="222" font-family="Inter, 'Segoe UI', Arial, Helvetica, system-ui, sans-serif" font-size="16.5" fill="#a1a1aa">Claude Code · Codex · Cursor · Cline · Copilot · Antigravity  →  <tspan fill="#7ee787" font-weight="700">FREE</tspan> Claude / GPT / Gemini · auto-fallback</text>
|
||||
|
||||
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
@@ -1,14 +1,14 @@
|
||||
---
|
||||
title: "OmniRoute MCP Server Documentation"
|
||||
version: 3.8.50
|
||||
lastUpdated: 2026-08-08
|
||||
version: 3.8.40
|
||||
lastUpdated: 2026-06-28
|
||||
---
|
||||
|
||||
# OmniRoute MCP Server Documentation
|
||||
|
||||
> Model Context Protocol server with 109 tools across routing, cache, compression, memory, skills, proxy, pool, Radar, and context source operations.
|
||||
> Model Context Protocol server with 105 tools across routing, cache, compression, memory, skills, proxy, pool, and context source operations.
|
||||
>
|
||||
> Source of truth: `open-sse/mcp-server/server.ts` computes **109 unique tools** with `countUniqueMcpTools()`: 44 canonical definitions (including the six CCR lifecycle tools, the agent-skills trio, and `omniroute_radar_catalog`), plus memory (3), skills (4), GitHub skills (3), pool (6), gamification (8), plugins (8), Notion (6), Obsidian (22), local corpus (3), and two RTK-only compression tools.
|
||||
> Source of truth: `open-sse/mcp-server/server.ts` computes **105 unique tools** with `countUniqueMcpTools()`: 42 canonical definitions (including the six CCR lifecycle tools and the agent-skills trio), plus memory (3), skills (4), GitHub skills (3), pool (6), gamification (8), plugins (8), Notion (6), Obsidian (22), and two RTK-only compression tools.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -64,7 +64,7 @@ Cursor, Cline, and compatible MCP client setup.
|
||||
|
||||
---
|
||||
|
||||
## Essential Tools (13) — Phase 1
|
||||
## Essential Tools (8) — Phase 1
|
||||
|
||||
| Tool | Scopes | Description |
|
||||
| :------------------------------ | :-------------------- | :------------------------------------------------------------ |
|
||||
@@ -72,15 +72,16 @@ Cursor, Cline, and compatible MCP client setup.
|
||||
| `omniroute_list_combos` | `read:combos` | All configured combos with strategies (optional metrics) |
|
||||
| `omniroute_get_combo_metrics` | `read:combos` | Performance metrics for a specific combo |
|
||||
| `omniroute_switch_combo` | `write:combos` | Activate or deactivate a combo |
|
||||
| `omniroute_create_combo` | `write:combos` | Create a validated combo through the existing combo API |
|
||||
| `omniroute_check_quota` | `read:quota` | Quota used/total, percent remaining, reset time, token health |
|
||||
| `omniroute_route_request` | `execute:completions` | Send a chat completion through OmniRoute routing |
|
||||
| `omniroute_cost_report` | `read:usage` | Cost report by period (session/day/week/month) |
|
||||
| `omniroute_list_models_catalog` | `read:models` | Full model catalog with capabilities, status, pricing |
|
||||
| `omniroute_radar_catalog` | `read:radar` | Local signed Radar catalog; optional provider/family filters |
|
||||
| `omniroute_tool_search` | `read:tools` | Discover tools from the registered MCP catalog |
|
||||
| `omniroute_web_search` | `execute:search` | Web search through the configured search providers |
|
||||
| `omniroute_web_fetch` | `execute:search` | Fetch web content through the configured fetch providers |
|
||||
|
||||
## Phase 1 — Search
|
||||
|
||||
| Tool | Scopes | Description |
|
||||
| :--------------------- | :--------------- | :--------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `omniroute_web_search` | `execute:search` | Web search through OmniRoute search gateway (Serper/Brave/Perplexity/Exa/Tavily/Google PSE/Linkup/SearchAPI/SearXNG) with failover |
|
||||
|
||||
## Advanced Tools (11) — Phase 2
|
||||
|
||||
@@ -226,7 +227,7 @@ See [AGENT-SKILLS.md](./AGENT-SKILLS.md) for the full catalog and how external a
|
||||
|
||||
## Related Frameworks (v3.8.0)
|
||||
|
||||
The MCP tool inventory above (109 unique tools, computed by `countUniqueMcpTools()`) is intentionally
|
||||
computed = 105, computed by `countUniqueMcpTools()`) is intentionally
|
||||
scoped to runtime routing/cache/compression/memory/skills/proxy/context-source operations. Two adjacent
|
||||
frameworks ship alongside the MCP server in v3.8.0 and are documented separately:
|
||||
|
||||
@@ -368,7 +369,7 @@ MCP tool, prompt, and resource registries can compress descriptions at registrat
|
||||
|
||||
Description compression shrinks each tool's metadata; **tool-cardinality reduction** goes one step further by reducing _how many_ tools are announced at all. Advertising fewer tools in the `tools/list` manifest cuts the per-request token cost the client's model pays for the tool catalog ("layer 5" compression). The implementation is a pure, stateless filter in `open-sse/mcp-server/toolCardinality.ts` (`reduceToolManifest`), wired into the registration loop in `createMcpServer()` (`open-sse/mcp-server/server.ts`).
|
||||
|
||||
**Opt-in, off by default.** The filter only runs when at least one of two environment variables is set; with neither set, all 109 tools are announced unchanged.
|
||||
**Opt-in, off by default.** The filter only runs when at least one of two environment variables is set; with neither set, all 105 tools are announced unchanged.
|
||||
|
||||
| Variable | Mode |
|
||||
| :--------------- | :-------------------------------------------------------------------------------------- |
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
---
|
||||
title: "Radar Free-Model Catalog"
|
||||
version: 3.8.50
|
||||
lastUpdated: 2026-08-13
|
||||
lastUpdated: 2026-08-08
|
||||
---
|
||||
|
||||
# Radar Free-Model Catalog
|
||||
|
||||
> **Source of truth:** `src/lib/radar/`, `src/lib/db/radar.ts`, `src/app/api/radar/`
|
||||
> **Last updated:** 2026-08-13 — v3.8.50
|
||||
> **Last updated:** 2026-08-08 — v3.8.50
|
||||
|
||||
Radar is an **optional add-on** that overlays a signed, freshly-curated free-model
|
||||
catalog on top of the release baseline (`FREE_MODEL_BUDGETS` in
|
||||
@@ -15,12 +15,11 @@ catalog on top of the release baseline (`FREE_MODEL_BUDGETS` in
|
||||
faster than release cadence — providers add, shrink, or discontinue free quotas between
|
||||
releases, and the baseline catalog can only be refreshed when a new version ships.
|
||||
|
||||
**Nothing that is free today stops being free because of the remote feed.** Radar never
|
||||
paywalls a baseline entry; it only refreshes limits/status fields at read time and can
|
||||
layer in newly-discovered free models between releases. An operator can still hide a
|
||||
model locally, and can restore it from the same dashboard. The baseline catalog itself
|
||||
is never mutated on disk — see
|
||||
[Read-time overlay merge rules](#read-time-overlay-merge-rules) below.
|
||||
**Nothing that is free today stops being free.** Radar never removes or paywalls a
|
||||
baseline entry; it only refreshes limits/status fields at read time and can layer in
|
||||
newly-discovered free models between releases. The baseline catalog itself is never
|
||||
mutated on disk — see [Read-time overlay merge rules](#read-time-overlay-merge-rules)
|
||||
below.
|
||||
|
||||
---
|
||||
|
||||
@@ -30,39 +29,14 @@ The following status distinguishes what this OSS release implements from later R
|
||||
workstreams. It is a code-level status, not a promise that a particular hosted deployment
|
||||
or external integration is currently available.
|
||||
|
||||
| Area | Status in this release |
|
||||
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| Signed catalog client | Implemented behind `RADAR_ENABLED`, with separate opt-in, Ed25519 verification, local encrypted settings/cache, persistent display/enabled overrides, reversible tombstones, scheduler, and dashboard. |
|
||||
| Contributor activation | The dashboard links to the server-hosted GitHub claim flow and accepts an existing `omr_…` key. Contributor eligibility is resolved by the private service; the OSS client contains no GitHub token or issuance logic. |
|
||||
| Supporter-key activation | Implemented. The raw key is validated, encrypted at rest, masked on reads, and sent only by server-side sync. Changing or clearing the key invalidates all four entitlement-sensitive feed caches. |
|
||||
| Referral links | Implemented as a separately signed, hourly-refreshed feed. Fixed links are available to the community tier immediately; limited campaigns remain live-tier data. |
|
||||
| Supporter offers | Implemented as a separate signed, live-only feed and dashboard page. The client revalidates the closed benefit schema, preserves the last good cache, filters expired entries, and labels partner offers explicitly. |
|
||||
| Intel and supporter recognition | Implemented as a strict signed live-only feed with Radar-owned ELO, factual catalog freshness/trend, a verified local supporter badge, dashboard page, and local-only CLI status/sync commands. |
|
||||
| Payments and transactional email | Not implemented in the OSS client. Purchase, donation, receipt review, recovery, and mail delivery belong to the private service; hosted availability still depends on its supervised deploy and provider configuration. |
|
||||
| Research-agent workstream | Not part of this client release. Curated feed contents remain server-side data; no autonomous research agent runs in an OmniRoute installation. |
|
||||
|
||||
---
|
||||
|
||||
## Public announcement reader
|
||||
|
||||
The generic announcement reader is separate from the Radar feature flag. The dashboard Home and
|
||||
Changelog viewer fetch the repository's public `news.json` through a plain `GET` to
|
||||
`NEWS_JSON_URL` (`src/shared/utils/releaseNotes.ts`). They send no Radar setting, prompt, provider
|
||||
configuration, usage record, or local dismissal state.
|
||||
|
||||
`news.json` uses the closed v2 schema implemented by `parseNewsPayload()`:
|
||||
|
||||
- `schemaVersion: 2` and a bounded `items[]` collection;
|
||||
- stable, unique announcement `id` values;
|
||||
- explicit `active` and ISO `publishedAt` fields;
|
||||
- required English copy with optional localized copy;
|
||||
- optional credential-free HTTPS links and an allowlisted icon;
|
||||
- newest-active-first selection, locale fallback to English, and per-ID local dismissal.
|
||||
|
||||
The parser temporarily accepts the former singular `{ active, title, message, ... }` shape so
|
||||
older forks can migrate without a broken Changelog view. Invalid feeds are inert. The Radar launch
|
||||
entry ships with `active: false`; changing it to `true` is a separate post-merge, post-deploy
|
||||
release action and does not change `RADAR_ENABLED` or the independent feed-sync opt-in.
|
||||
| Area | Status in this release |
|
||||
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Signed catalog client | Implemented behind `RADAR_ENABLED`, with separate opt-in, Ed25519 verification, local encrypted settings/cache, non-destructive overlay, scheduler, and dashboard. |
|
||||
| Contributor activation | The dashboard links to the server-hosted GitHub claim flow and accepts an existing `omr_…` key. Contributor eligibility is resolved by the private service; the OSS client contains no GitHub token or issuance logic. |
|
||||
| Supporter-key activation | Implemented. The raw key is validated, encrypted at rest, masked on reads, and sent only by the server-side sync. Changing or clearing the key invalidates both entitlement-sensitive feed caches. |
|
||||
| Referral links | Implemented as a separately signed, hourly-refreshed feed. Fixed links are available to the community tier immediately; limited campaigns remain live-tier data. |
|
||||
| Payments and transactional email | Not implemented in the OSS client. Purchase, donation, receipt review, and mail delivery belong to the private service and its later operational workstream. |
|
||||
| Research-agent workstream | Not part of this client release. Curated feed contents remain server-side data; no autonomous research agent runs in an OmniRoute installation. |
|
||||
|
||||
---
|
||||
|
||||
@@ -74,16 +48,15 @@ Radar is gated end-to-end by the `RADAR_ENABLED` feature flag
|
||||
|
||||
**When the flag is off, the surface does not exist:**
|
||||
|
||||
- All `/api/radar/*` endpoints, including local model-state reads and writes,
|
||||
- `GET /api/radar/catalog`, `POST /api/radar/sync`, `POST /api/radar/settings` all
|
||||
return `404` before touching any Radar module.
|
||||
- The dashboard screens (`/dashboard/radar`, `/dashboard/radar/setup`,
|
||||
`/dashboard/radar/combos`, `/dashboard/radar/offers`, `/dashboard/radar/intel`) render
|
||||
- The dashboard screens (`/dashboard/radar`, `/dashboard/radar/setup`) render
|
||||
`notFound()`.
|
||||
- `getRadarCatalog()` (`src/lib/radar/index.ts`) returns the untouched baseline —
|
||||
same entry count, same values, every entry tagged `origin: "baseline"` — and never
|
||||
reads the feed cache.
|
||||
- No Radar network call is ever made; each sync module returns `{ status: "disabled" }`
|
||||
before touching `fetch`.
|
||||
- No network call is ever made; `syncRadar()` (`src/lib/radar/sync.ts`) returns
|
||||
`{ status: "disabled" }` at step 1 without touching `fetch`.
|
||||
|
||||
This is a strict superset gate: flipping the flag on unlocks the _screens_, nothing
|
||||
more. It does not upload data, does not start a background sync, and does not change
|
||||
@@ -105,17 +78,14 @@ Opt-in false → { status: "opt_out" } — no network call
|
||||
|
||||
When both are on, the sync path is:
|
||||
|
||||
1. `GET <feed base URL>/v1/catalog/latest` with `x-omniroute-radar-schema: 2` and an optional
|
||||
`Authorization: Bearer <supporter key>` header (see below). Servers default to the separately
|
||||
signed v1 transition artifact when the schema header is absent, so older installed clients keep
|
||||
receiving updates.
|
||||
1. `GET <feed base URL>/v1/catalog/latest` with an optional `Authorization: Bearer
|
||||
<supporter key>` header (see below).
|
||||
2. Nothing about the request, the operator, or their traffic is uploaded — it is a
|
||||
plain, unauthenticated-by-default GET. OmniRoute never posts usage data, provider
|
||||
configuration, or model traffic to the feed service.
|
||||
3. The response is verified, validated, and cached locally (see
|
||||
[Security model](#security-model)). Radar has exactly four server-side network paths:
|
||||
`syncRadar()` for the catalog, `syncRadarReferrals()` for referrals, and
|
||||
`syncRadarOffers()` / `syncRadarIntel()` for supporter-only offers and Intel.
|
||||
[Security model](#security-model)). Radar has exactly two server-side network paths:
|
||||
`syncRadar()` for the catalog and `syncRadarReferrals()` for the standalone referrals feed.
|
||||
|
||||
The **supporter key** is an optional Bearer token (`radar_settings.supporter_key`)
|
||||
that lets the feed service decide which tier to serve (see
|
||||
@@ -125,7 +95,7 @@ that lets the feed service decide which tier to serve (see
|
||||
helpers (`src/lib/db/encryption.ts`) used for provider credentials.
|
||||
- Set via `POST /api/radar/settings` (`{ supporterKey: "omr_" + 40 hex chars }`) and
|
||||
**never echoed back** — the response returns a masked form (`omr_****abcd`).
|
||||
- Changing or clearing it atomically invalidates the catalog, referrals, offers, and Intel caches. The
|
||||
- Changing or clearing it atomically invalidates both the catalog and referrals caches. The
|
||||
next sync/read resolves the new entitlement server-side; saving a key does not itself make
|
||||
a network request or consume a single-use activation key.
|
||||
- Sent to the feed service as a Bearer token on the sync GET — nothing else about the
|
||||
@@ -158,29 +128,6 @@ client component never reads `process.env` itself.
|
||||
| `RADAR_CONTRIBUTOR_CLAIM_URL` | Overrides the contributor-claim URL (default `https://radar.omniroute.online/auth/github`). |
|
||||
| `RADAR_SUPPORTER_PLANS_URL` | Overrides the supporter-plans URL (default `https://radar.omniroute.online/planos`). |
|
||||
|
||||
### Recovering a lost supporter key
|
||||
|
||||
The hosted service's recovery entry point is `https://radar.omniroute.online/recover`; it is also
|
||||
linked from the plans page. Recovery remains entirely outside the OSS client because the local
|
||||
installation never receives the purchaser/contributor e-mail and cannot reconstruct a raw key from
|
||||
its encrypted settings.
|
||||
|
||||
1. Submit the e-mail associated with the key. The service returns the same accepted page whether a
|
||||
recoverable license exists or not, so the form does not enumerate accounts.
|
||||
2. If eligible, the delivery worker sends a short-lived, one-use link. Opening it immediately moves
|
||||
the token into a transient encrypted `HttpOnly`/`Secure` cookie and redirects to the clean
|
||||
`/recover` URL; the page contains no token, e-mail, old key, or replacement key.
|
||||
3. Confirm the revocation. The private service revokes the prior key, creates the replacement with
|
||||
the same plan/expiration, and queues it for e-mail in one transaction. The replacement is never
|
||||
returned to the browser.
|
||||
4. Paste the replacement into `/dashboard/radar`. The old key must now degrade to `community`; the
|
||||
replacement must produce a verified `live` sync. Reopening the same recovery link must fail with
|
||||
a generic invalid/expired response.
|
||||
|
||||
The hosted recovery route and mail worker can be present in code while still unavailable in a given
|
||||
deployment. Do not call the flow production-ready until the server has been deployed, the delivery
|
||||
provider has been configured with a controlled recipient, and the full one-use link has been tested.
|
||||
|
||||
Once a visitor has a key (`omr_` + 40 hex chars), the activation screen
|
||||
(`src/app/(dashboard)/dashboard/radar/page.tsx`) has a paste-key input as the primary
|
||||
path: pasting a key and submitting sends `POST /api/radar/settings`
|
||||
@@ -194,57 +141,6 @@ paste a new one — the raw key is never redisplayed. The two claim/plans button
|
||||
remain the way to _obtain_ a key in the first place; this input is where an operator
|
||||
who already has one activates it.
|
||||
|
||||
### End-to-end activation and guided setup
|
||||
|
||||
The private feed service and this OSS client have a deliberately narrow boundary: the service
|
||||
issues and validates the supporter key, while the local OmniRoute installation encrypts the key,
|
||||
syncs signed artifacts server-side, and guides provider setup. The assisted validation order is:
|
||||
|
||||
1. Obtain a newly issued or recovered key from the contributor claim, plans/checkout, recovery
|
||||
journey, or an authorized private server operator. Do not paste the raw key into logs,
|
||||
screenshots, issue comments, or command-line arguments.
|
||||
2. Enable the `RADAR_ENABLED` feature flag on the local OmniRoute installation. This exposes the UI
|
||||
but remains network-inert until the separate opt-in is saved.
|
||||
3. Open `/dashboard/radar`, paste the key, and activate. The browser sends one local
|
||||
`POST /api/radar/settings` with `{ optIn: true, supporterKey }`; the key is encrypted locally and
|
||||
the response contains only `omr_****<last4>`.
|
||||
4. Let the activation screen run its catalog sync, or select **Sync now**. Confirm that the page
|
||||
reports `live`, a feed version, and a fetch time. For an authenticated local diagnostic,
|
||||
`GET /api/radar/status` reports opt-in/key presence and the four cache states without returning
|
||||
the key. `POST /api/radar/sync-all` can refresh catalog, referrals, offers, and Intel explicitly.
|
||||
5. Open `/dashboard/radar/setup?provider=<provider>`. Follow the provider-owned credential URL,
|
||||
select **Add API key**, save through the real provider form, return to the guide, and run
|
||||
**Test connection**. The guide uses the normal `/api/providers` and
|
||||
`/api/providers/<connection-id>/test` routes; it does not create a parallel Radar credential.
|
||||
6. Open `/dashboard/radar/combos` after at least two compatible provider connections are active.
|
||||
Review the suggested family and create the combo through the existing combo API. Offers and
|
||||
Intel remain separate live-only signed caches and can be checked on their dedicated Radar pages.
|
||||
7. Reload `/dashboard/radar` and the setup page. The opt-in, masked-key state, verified cache, saved
|
||||
provider connection, and test action must survive the reload. Capture evidence only after the
|
||||
raw key and provider credential are no longer visible.
|
||||
|
||||
Saving a key is not itself proof of live entitlement. The proof is the combination of the private
|
||||
service's `GET /v1/license/check` result, the OSS catalog's served `live` tier, a verified signed
|
||||
cache, and the real provider connection/test flow. An invalid, expired, or revoked key safely
|
||||
degrades the catalog to `community`; it must not be reported as a successful live-key validation.
|
||||
|
||||
### Private admin-panel link
|
||||
|
||||
`RADAR_ADMIN_URL` optionally adds **Radar Admin ↗** immediately after the user-facing
|
||||
Radar item in the Costs sidebar section. It has deliberately no default: when the variable is
|
||||
unset or invalid, the static sidebar, command palette, and sidebar-customization screen contain no
|
||||
admin item and no private URL.
|
||||
|
||||
The value is resolved server-side and relayed through the management-authenticated
|
||||
`GET /api/settings` response only to an authenticated dashboard session, or to the trusted
|
||||
loopback owner during a local no-login bootstrap. CLI, internal-service, and manage-scope API-key
|
||||
authentication do not receive it. The browser validates the response again before materializing
|
||||
the external link, which opens with `noopener noreferrer`.
|
||||
|
||||
Use a credential-free HTTPS tunnel/tailnet URL. Plain HTTP is accepted only for a loopback SSH
|
||||
forward such as `http://127.0.0.1:9351`; other schemes, embedded credentials, malformed URLs, and
|
||||
remote HTTP destinations fail closed and leave navigation inert.
|
||||
|
||||
---
|
||||
|
||||
## Security model
|
||||
@@ -375,54 +271,6 @@ Four rules, in order of precedence:
|
||||
entry (`tombstones` set), the feed re-adding that `provider:modelId` in a later
|
||||
version does not bring it back.
|
||||
|
||||
The editable fields and tombstones are persisted in
|
||||
`radar_local_model_state` (migration `153_radar_local_model_state.sql`). The public DB
|
||||
adapter (`src/lib/db/radar.ts`) converts those rows into the `localOverrides` map and
|
||||
`tombstones` set used by `applyFeed()`; production `getRadarCatalog()` loads that state
|
||||
after the flag, cache, and schema gates pass. Only `displayName` and `enabled` are
|
||||
operator-editable. Provider/model identity, feed provenance, quota, capabilities, ToS,
|
||||
and setup data cannot be written through this surface.
|
||||
|
||||
The dashboard exposes four local actions:
|
||||
|
||||
- **Edit** changes the local display name and enabled state.
|
||||
- **Reset local changes** clears both editable fields without changing a tombstone.
|
||||
- **Hide** creates a tombstone, so later feed updates cannot recreate the row.
|
||||
- **Restore** removes the tombstone; any separately-saved override remains in effect.
|
||||
|
||||
A feed `enabled: false` remains the safety exception: it wins over a stale local
|
||||
`enabled: true`, keeps the merged entry disabled, and records `disabledBy: "radar"`.
|
||||
|
||||
Catalog publications use `schemaVersion: 2`. `contextWindow` and each of `tools`, `vision`, and
|
||||
`thinking` are independently `number | null` / `boolean | null`: `null` means unknown, while
|
||||
`false` means a D16-confirmed official provider source explicitly says the capability is absent.
|
||||
Internal OmniRoute registry/model-spec flags are never promoted directly to feed facts. The client
|
||||
still accepts v1 snapshots; because the old builder used `false` as an absence placeholder, v1 `false` is
|
||||
normalized to unknown while v1 `true` remains factual. Unknown schema versions fail closed and the
|
||||
last valid cache remains available. Every v2 model with a non-null context/capability must carry a
|
||||
credential-free HTTPS `metadataEvidenceUrls[]`; otherwise schema validation fails and the cache is
|
||||
not replaced. The catalog table renders all three states as `✓`, `✕`, and `?`.
|
||||
|
||||
### Guided combos and MCP access
|
||||
|
||||
Confirmed `familyId` values survive the read-time overlay and drive the pure
|
||||
`buildRadarComboSuggestions()` module (`src/lib/radar/comboSuggestions.ts`). A family is suggested
|
||||
only when at least two distinct providers have active connections and expose the exact curated model
|
||||
ID. Disabled models, inactive providers, missing model IDs, singleton families, and ambiguous
|
||||
alias/prefix matches fail closed. Suggestions use the existing `priority` strategy, ordering the
|
||||
largest recurring monthly budget first; the UI creates them only through `POST /api/combos`.
|
||||
|
||||
The guided UI lives at `/dashboard/radar/combos`. It reads only the local
|
||||
`GET /api/radar/catalog` and `GET /api/combos/builder/options` endpoints. It never triggers Radar sync,
|
||||
reads provider credentials, or writes directly to the combo database.
|
||||
|
||||
MCP clients can read the same local projection with `omniroute_radar_catalog` (`read:radar`). The
|
||||
optional `provider`, `familyId`, and `enabledOnly` filters are evaluated after one local
|
||||
`GET /api/radar/catalog` read. Its closed output includes catalog metadata plus provider/model,
|
||||
display name, `familyId`, quota, capabilities, enabled state, origin, and `disabledBy`; setup URLs,
|
||||
steps, connections, e-mail addresses, keys, and referral data are never returned. This tool is
|
||||
read-only and never invokes `/api/radar/sync`.
|
||||
|
||||
### Provenance markers
|
||||
|
||||
Every merged entry carries an `origin` field the UI renders as a badge:
|
||||
@@ -436,41 +284,30 @@ Every merged entry carries an `origin` field the UI renders as a badge:
|
||||
|
||||
## Local surfaces — never a feed proxy
|
||||
|
||||
The local Radar route families below back the UI under `src/app/api/radar/`:
|
||||
Five local routes back the UI, all under `src/app/api/radar/`:
|
||||
|
||||
| Route | Method | Purpose |
|
||||
| ------------------------------ | ------ | --------------------------------------------------------------------------------------------------------------------- |
|
||||
| `/api/radar/catalog` | GET | Returns the merged catalog (`getRadarCatalog()`) from the local cache. |
|
||||
| `/api/radar/sync` | POST | Triggers `syncRadar()` server-side; returns the resulting status. |
|
||||
| `/api/radar/settings` | GET | Returns `{ optIn, hasSupporterKey, supporterKeyMasked }` — never the raw key. |
|
||||
| `/api/radar/settings` | POST | Sets opt-in and/or the (encrypted) supporter key. |
|
||||
| `/api/radar/referrals` | GET | Returns `{ fixed, campaigns, tier }` from the local cache — see [Referral links](#referral-links-free-credits) below. |
|
||||
| `/api/radar/offers` | GET | Returns active offers from the verified local live cache; never returns the supporter key. |
|
||||
| `/api/radar/offers/sync` | POST | Triggers the server-side, live-key-only `syncRadarOffers()` pipeline. |
|
||||
| `/api/radar/intel` | GET | Returns verified local live Intel plus a supporter-recognition boolean; never an identity or key. |
|
||||
| `/api/radar/intel/sync` | POST | Triggers the server-side, live-key-only `syncRadarIntel()` pipeline. |
|
||||
| `/api/radar/status` | GET | Returns read-only local settings/cache status for catalog, referrals, offers, and Intel, without secrets. |
|
||||
| `/api/radar/sync-all` | POST | Runs all four server-side sync modules and returns a separate status for each feed. |
|
||||
| `/api/radar/local-model-state` | GET | Lists persisted overrides and tombstones for edit/restore controls. |
|
||||
| `/api/radar/local-model-state` | PATCH | Sets or clears the validated `displayName`/`enabled` override fields. |
|
||||
| `/api/radar/local-model-state` | PUT | Creates or removes a tombstone with `{ provider, modelId, tombstoned }`. |
|
||||
| `/api/radar/local-model-state` | DELETE | Clears editable override fields while preserving any tombstone. |
|
||||
| Route | Method | Purpose |
|
||||
| ---------------------- | ------ | --------------------------------------------------------------------------------------------------------------------- |
|
||||
| `/api/radar/catalog` | GET | Returns the merged catalog (`getRadarCatalog()`) from the local cache. |
|
||||
| `/api/radar/sync` | POST | Triggers `syncRadar()` server-side; returns the resulting status. |
|
||||
| `/api/radar/settings` | GET | Returns `{ optIn, hasSupporterKey, supporterKeyMasked }` — never the raw key. |
|
||||
| `/api/radar/settings` | POST | Sets opt-in and/or the (encrypted) supporter key. |
|
||||
| `/api/radar/referrals` | GET | Returns `{ fixed, campaigns, tier }` from the local cache — see [Referral links](#referral-links-free-credits) below. |
|
||||
|
||||
**Hard rule: these routes never proxy the feed service.** The browser only ever talks
|
||||
to the local OmniRoute server. The four modules that touch the Radar service are
|
||||
`src/lib/radar/sync.ts` (catalog), `src/lib/radar/referralsSync.ts` (referrals), and
|
||||
`src/lib/radar/offersSync.ts` (offers) plus `src/lib/radar/intelSync.ts` (Intel); all run
|
||||
server-side, never client-side. This keeps
|
||||
the feed URL and any supporter key out of client-facing network traffic entirely.
|
||||
to the local OmniRoute server. The two modules that touch the Radar service are
|
||||
`src/lib/radar/sync.ts` (catalog) and `src/lib/radar/referralsSync.ts` (referrals); both
|
||||
always run server-side, never client-side. This keeps the feed URL and any supporter key
|
||||
out of client-facing network traffic entirely.
|
||||
|
||||
All Radar endpoints return `404` when `RADAR_ENABLED` is off (see
|
||||
All five routes return `404` when `RADAR_ENABLED` is off (see
|
||||
[Flag](#flag-radar_enabled-default-off) above), and route error responses through
|
||||
`buildErrorBody()`/`sanitizeErrorMessage()` per the repo-wide error-sanitization rule
|
||||
(`docs/security/ERROR_SANITIZATION.md`).
|
||||
|
||||
### Authentication
|
||||
|
||||
All Radar endpoints require authentication via `isAuthenticated()`
|
||||
All five routes require authentication via `isAuthenticated()`
|
||||
(`src/shared/utils/apiAuth.ts`) — a dashboard session cookie or a management-scoped
|
||||
API key, the same gate that protects the rest of `/api/settings/*`. The flag-off
|
||||
`404` check always runs **before** the auth check, so an install with `RADAR_ENABLED`
|
||||
@@ -481,58 +318,6 @@ auth state — only the masked form and a `hasSupporterKey` boolean.
|
||||
|
||||
---
|
||||
|
||||
## Supporter offers
|
||||
|
||||
Offers use their own signed artifact, `GET /v1/offers/latest`, and never share the catalog or
|
||||
referrals cache. The server endpoint requires a valid live supporter Bearer key; there is no
|
||||
community fallback. `syncRadarOffers()` therefore stops before the network when the feature flag is
|
||||
off, the operator has not opted in, or no supporter key is configured.
|
||||
|
||||
After a successful GET, the client verifies the Ed25519 signature over the exact response bytes,
|
||||
validates `RadarOffersFeedSchema`, requires both the signed body and
|
||||
`x-omniroute-feed-tier` header to say `live`, enforces a strictly newer dotted version, and only then
|
||||
atomically replaces `radar_offers_cache` (migration `144_radar_offers_cache.sql`). The same 10 MB
|
||||
header-plus-stream cap used by the other feeds applies. Signature, schema, tier, replay, size, HTTP,
|
||||
and network failures all preserve the last verified cache.
|
||||
|
||||
The closed offer shape supports three comparable benefit types: percentage in basis points, credit
|
||||
in minor currency units, or trial days. A partner offer must include a same-kind public baseline and
|
||||
its benefit must be strictly greater; official offers have no partner baseline. URLs must be
|
||||
credential-free HTTPS. `getRadarOffers()` defensively revalidates the cached payload and filters
|
||||
expired entries on every local read; `/dashboard/radar/offers` filters expiry again before rendering,
|
||||
uses Portuguese text when available with English fallback, and labels partner offers explicitly.
|
||||
|
||||
The browser calls only local routes: it reads the masked settings snapshot, asks
|
||||
`POST /api/radar/offers/sync` to refresh server-side, then reads `GET /api/radar/offers`. Without a
|
||||
key it shows the existing contributor/support links instead of attempting a feed request. External
|
||||
offer links open in a new tab with `noopener noreferrer`. No `radar_offers` MCP tool is exposed in
|
||||
this release.
|
||||
|
||||
---
|
||||
|
||||
## Radar Intel, supporter badge, and CLI
|
||||
|
||||
Intel is a signed artifact at `GET /v1/intel/latest`. The closed `RadarIntelFeedSchema` accepts
|
||||
only Radar-owned ELO rankings derived by the private curator from confirmed comparisons and factual
|
||||
catalog age/count deltas derived from signed catalog snapshots. The methodology is fixed at initial
|
||||
rating 1000 and K=32. An empty ranking is valid when no comparison has been confirmed; the client
|
||||
never synthesizes one.
|
||||
|
||||
`syncRadarIntel()` applies the same server-side Bearer, 30-second timeout, 10 MiB streamed cap,
|
||||
exact-byte Ed25519 verification, strict schema, `live` body/header requirement, version floor, and
|
||||
last-good-cache preservation as offers. After a verified live snapshot is persisted, the client
|
||||
derives `radar:<sha256(supporter key)>`, stores only that one-way identity, and emits the dedicated
|
||||
`radar_supporter` recognition event. Its `radar-supporter` badge is idempotent and awards zero XP;
|
||||
it never updates leaderboards or reuses `token_share`. `/dashboard/radar/intel` renders the badge
|
||||
only from verified local cache metadata.
|
||||
|
||||
The CLI exposes `omniroute radar status` and `omniroute radar sync`. Both communicate only with the
|
||||
local OmniRoute API. `status` performs a read-only `GET /api/radar/status`; `sync` sends one
|
||||
`POST /api/radar/sync-all` and prints a result per feed. Neither command reads, accepts, or prints
|
||||
the supporter key, and neither contacts the Radar service directly.
|
||||
|
||||
---
|
||||
|
||||
## Referral links (free credits)
|
||||
|
||||
Referral links are served from a **standalone, always-current** feed —
|
||||
@@ -688,9 +473,8 @@ service without touching client code:
|
||||
|
||||
1. Serve a `GET /v1/catalog/latest` endpoint returning a JSON body that satisfies
|
||||
`RadarFeedSchema` (`src/lib/radar/feedSchema.ts`) — top-level `feed:
|
||||
"omniroute-radar"`, `schemaVersion: 2`, `version`, `tier`, `providers`, `models`,
|
||||
`quirks`, and `totals`. Honor `x-omniroute-radar-schema: 2`; a transition-compatible server
|
||||
should default requests without it to a separately signed v1 artifact.
|
||||
"omniroute-radar"`, `schemaVersion: 1`, `version`, `tier`, `providers`, `models`,
|
||||
`quirks`, and `totals`.
|
||||
2. Sign the exact response bytes with an Ed25519 key pair and return the base64
|
||||
signature in the `x-omniroute-feed-signature` response header.
|
||||
3. Set `RADAR_FEED_URL` to the new base URL and `RADAR_FEED_PUBKEY` to the matching
|
||||
@@ -714,24 +498,11 @@ instead of failing the rest of the page. To also offer referral links, serve
|
||||
(`src/lib/radar/referralsFeedSchema.ts`) and sign it with the same Ed25519 key pair as
|
||||
the catalog feed.
|
||||
|
||||
Supporter offers are another optional artifact. To serve them, implement
|
||||
`GET /v1/offers/latest` with the closed `RadarOffersFeedSchema`
|
||||
(`src/lib/radar/offersFeedSchema.ts`), require live entitlement, return
|
||||
`x-omniroute-feed-tier: live`, and sign the exact bytes with the same key. A fork that omits this
|
||||
endpoint keeps the catalog/referrals behavior unchanged; offer refresh fails non-destructively and
|
||||
the last verified local offer cache remains available.
|
||||
|
||||
Intel is optional in the same way. A self-hoster can serve `GET /v1/intel/latest` using
|
||||
`RadarIntelFeedSchema` (`src/lib/radar/intelFeedSchema.ts`), require live entitlement, return
|
||||
`x-omniroute-feed-tier: live`, and sign the exact bytes with the shared Ed25519 key. Omitting the
|
||||
endpoint leaves catalog, referrals, and offers unchanged; Intel refresh preserves any last verified
|
||||
local snapshot.
|
||||
|
||||
---
|
||||
|
||||
## Related docs
|
||||
|
||||
- [`docs/security/ERROR_SANITIZATION.md`](../security/ERROR_SANITIZATION.md) — the
|
||||
error-response pattern the `/api/radar/*` routes follow.
|
||||
error-response pattern the five `/api/radar/*` routes follow.
|
||||
- [`docs/reference/ENVIRONMENT.md`](../reference/ENVIRONMENT.md#27-radar-feed-self-hosting)
|
||||
— `RADAR_FEED_URL` / `RADAR_FEED_PUBKEY` reference.
|
||||
|
||||
@@ -79,7 +79,7 @@ Use a real key instead when your OmniRoute server is protected or remote.
|
||||
|
||||
Codex CLI deprecated `wire_api = "chat"` (Chat Completions) in February 2026 and now **requires** `wire_api = "responses"` (OpenAI Responses API). Setting `wire_api = "chat"` causes an immediate startup crash since v0.138.
|
||||
|
||||
Many providers, including GLM and Kimi, still expose only a Chat Completions endpoint. DeepSeek V4 now exposes a native Responses API as well as an Anthropic-compatible endpoint; OmniRoute uses Responses by default and lets each DeepSeek connection select Anthropic compatibility.
|
||||
DeepSeek, GLM, Kimi and others only expose a Chat Completions endpoint — not the Responses API. If you pointed Codex directly at them, it would fail.
|
||||
|
||||
**OmniRoute solves this transparently:**
|
||||
|
||||
@@ -87,8 +87,8 @@ Many providers, including GLM and Kimi, still expose only a Chat Completions end
|
||||
Codex CLI
|
||||
→ wire_api = "responses"
|
||||
→ POST /v1/responses (OmniRoute)
|
||||
→ OmniRoute selects the provider's native protocol and translates when needed
|
||||
→ POST /responses (DeepSeek V4) or /chat/completions (Mistral / GLM / Kimi / others)
|
||||
→ OmniRoute Responses ↔ Chat Completions transformer
|
||||
→ POST /chat/completions (DeepSeek / Mistral / GLM / Kimi / any provider)
|
||||
```
|
||||
|
||||
You never need a separate translation proxy when using OmniRoute. **All models use `wire_api = "responses"`** — OmniRoute handles the rest.
|
||||
|
||||
@@ -14,7 +14,6 @@ lastUpdated: 2026-06-28
|
||||
- [With Environment File](#with-environment-file)
|
||||
- [Docker Compose](#docker-compose)
|
||||
- [Available Profiles](#available-profiles)
|
||||
- [Configuring host CLI tools when OmniRoute runs in Docker](#configuring-host-cli-tools-when-omniroute-runs-in-docker)
|
||||
- [Redis Sidecar](#redis-sidecar)
|
||||
- [Production Compose](#production-compose)
|
||||
- [Dockerfile Stages](#dockerfile-stages)
|
||||
@@ -83,61 +82,6 @@ OmniRoute ships four Compose profiles. Pick the one that matches your environmen
|
||||
|
||||
> Multiple profiles can be combined: `docker compose --profile cli --profile cliproxyapi up -d`.
|
||||
|
||||
## Configuring host CLI tools when OmniRoute runs in Docker
|
||||
|
||||
`omniroute setup-codex`, `setup-claude`, `config set <tool>` and the dashboard's
|
||||
**Save config** button all write files like `~/.codex/*.config.toml`. Those paths
|
||||
only mean something on the machine where the CLI actually runs. Run them inside
|
||||
the container and the write lands in the container's own home (`/home/node` —
|
||||
the image runs `USER node`), where no host CLI will ever read it and where it is
|
||||
discarded the moment the container is recreated.
|
||||
|
||||
OmniRoute detects this and refuses the write with instructions instead of
|
||||
reporting a success you cannot use: the CLI exits `2`, and the API answers `422`
|
||||
with `containerEphemeralTarget: true`.
|
||||
|
||||
### Recommended: run the CLI on the host, OmniRoute in Docker
|
||||
|
||||
The container serves the API; the CLI configures your host tools.
|
||||
|
||||
```bash
|
||||
docker compose --profile base up -d
|
||||
|
||||
npm install -g omniroute
|
||||
omniroute connect http://localhost:20128 # point the CLI at the container
|
||||
omniroute setup-codex # writes the real ~/.codex on your host
|
||||
```
|
||||
|
||||
This is the right choice when Codex, Claude Code, Cursor or similar run on your
|
||||
laptop — which is the usual setup.
|
||||
|
||||
### Alternative: bind-mount the host config dirs (`host` profile)
|
||||
|
||||
If you want the container itself to write your host config, mount the
|
||||
directories in and point `CLI_CONFIG_HOME` at the mount root. The `host` profile
|
||||
already does this:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
- CLI_CONFIG_HOME=/host-home
|
||||
- CLI_ALLOW_CONFIG_WRITES=true
|
||||
volumes:
|
||||
- ~/.codex:/host-home/.codex:rw
|
||||
- ~/.claude:/host-home/.claude:rw
|
||||
```
|
||||
|
||||
A bind mount is what makes the path trustworthy: OmniRoute reads
|
||||
`/proc/self/mountinfo` and allows writes to mounted paths (and to directories
|
||||
whose children are mounts, which is exactly the `/host-home` shape above) while
|
||||
still refusing unmounted ones.
|
||||
|
||||
### Escape hatch: configure the container's own CLIs
|
||||
|
||||
When the CLIs genuinely live inside the container (the `cli` profile), the write
|
||||
is intentional. Pass `--allow-container-write` to any `setup-*` command, or set
|
||||
`OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE=true` for the server. The write proceeds
|
||||
with a warning that it will not survive the container.
|
||||
|
||||
## Redis Sidecar
|
||||
|
||||
OmniRoute relies on Redis to back the distributed rate limiter and shared cache. The `redis` service is **always defined** in `docker-compose.yml` (it has no profile gate) and starts alongside any other profile.
|
||||
@@ -326,22 +270,7 @@ prefix). Traefik should route `PathPrefix(`/omniroute`)` to the container withou
|
||||
`/omniroute/_next/...`.
|
||||
|
||||
The Docker healthcheck probes `/api/monitoring/health` prefixed with the active
|
||||
`OMNIROUTE_BASE_PATH`. That path is a **deep** check (DB + monitoring summary). It is
|
||||
appropriate for Docker’s infrequent `HEALTHCHECK`, but **not** for Kubernetes
|
||||
`livenessProbe` intervals.
|
||||
|
||||
For orchestrators (Kubernetes, Nomad, etc.):
|
||||
|
||||
| Probe | Prefer | Avoid |
|
||||
| --- | --- | --- |
|
||||
| Liveness | TCP on the main port (`PORT`, default `20128`), or soft HTTP `/healthz` | `/api/monitoring/health` as liveness |
|
||||
| Readiness | HTTP `GET /healthz` | Tight timeouts that treat event-loop busy as dead |
|
||||
| Deep / blackbox | `/api/monitoring/health` | — |
|
||||
|
||||
`/healthz` only reports process lifecycle (`ok` / `starting` / `stopping`). It still
|
||||
runs on the same Node event loop as request handling, so CPU-bound catalog or
|
||||
compression work can delay it — busy ≠ dead. Full probe guidance:
|
||||
[Monitoring guide — Kubernetes probe recommendations](../ops/MONITORING_GUIDE.md#kubernetes-probe-recommendations).
|
||||
`OMNIROUTE_BASE_PATH`.
|
||||
|
||||
## Docker Compose with Caddy (HTTPS Auto-TLS)
|
||||
|
||||
|
||||
@@ -39,15 +39,15 @@ system tray, auto-updater, IPC bridge, and zero-config secret bootstrap.
|
||||
|
||||
Confirmed from `electron/package.json`:
|
||||
|
||||
| Package | Version |
|
||||
| ------------------ | --------------------------------------------------------- |
|
||||
| `electron` | `^41.5.1` |
|
||||
| `electron-builder` | `^26.10.0` |
|
||||
| `electron-updater` | `^6.8.5` |
|
||||
| `better-sqlite3` | root `^13.0.2` (Node-API prebuilds — no Electron rebuild) |
|
||||
| App version | `3.8.0` |
|
||||
| App id | `online.omniroute.desktop` |
|
||||
| Product name | `OmniRoute` |
|
||||
| Package | Version |
|
||||
| ------------------ | -------------------------- |
|
||||
| `electron` | `^41.5.1` |
|
||||
| `electron-builder` | `^26.10.0` |
|
||||
| `electron-updater` | `^6.8.5` |
|
||||
| `better-sqlite3` | `^12.9.0` |
|
||||
| App version | `3.8.0` |
|
||||
| App id | `online.omniroute.desktop` |
|
||||
| Product name | `OmniRoute` |
|
||||
|
||||
## Scripts (root `package.json`)
|
||||
|
||||
@@ -260,14 +260,14 @@ Releases are published to GitHub Releases (`diegosouzapw/OmniRoute`), which is a
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Fix |
|
||||
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `Cannot find module 'better-sqlite3'` after Electron major bump | better-sqlite3 v13 ships Node-API prebuilds — re-run `npm install` at the root and `prepare:bundle` (it verifies the prebuild for the current platform) |
|
||||
| `ERR_DLOPEN_FAILED` for native module | Re-run `prepare:bundle` — it fails fast when the Node-API prebuild for the current platform is missing |
|
||||
| Window appears blank on Linux | Confirm Next.js server actually bound to PORT (check `[Server]` logs) |
|
||||
| macOS notarization stalls | Ensure `APPLE_*` vars are exported, not just in `.env` |
|
||||
| Windows SmartScreen warning | Sign with EV cert, or users right-click → "Run anyway" |
|
||||
| Smoke test fails with port-in-use | Stop any local dev server on 20128 before running `electron:smoke:packaged` |
|
||||
| Symptom | Fix |
|
||||
| --------------------------------------------------------------- | --------------------------------------------------------------------------- |
|
||||
| `Cannot find module 'better-sqlite3'` after Electron major bump | `cd electron && npm rebuild` |
|
||||
| `ERR_DLOPEN_FAILED` for native module | Re-run `prepare:bundle` and verify ABI matches Electron's Node |
|
||||
| Window appears blank on Linux | Confirm Next.js server actually bound to PORT (check `[Server]` logs) |
|
||||
| macOS notarization stalls | Ensure `APPLE_*` vars are exported, not just in `.env` |
|
||||
| Windows SmartScreen warning | Sign with EV cert, or users right-click → "Run anyway" |
|
||||
| Smoke test fails with port-in-use | Stop any local dev server on 20128 before running `electron:smoke:packaged` |
|
||||
|
||||
## See Also
|
||||
|
||||
|
||||
@@ -38,36 +38,6 @@ Common problems and solutions for OmniRoute.
|
||||
|
||||
---
|
||||
|
||||
### Rate Limiting on Free Providers (429 / 400 / 401)
|
||||
|
||||
**Symptom**: When using `model: "auto"` with free/no-auth providers (opencode, felo-web, auggie, etc.), you intermittently get `HTTP 429`, `400`, or `401` instead of answers. The requests succeed when retrying the same prompt moments later, but automation (cron jobs, agents, scripts) breaks on the first failure.
|
||||
|
||||
**Root cause**: Three independent failure modes stack up:
|
||||
|
||||
1. **Provider rate-limit (`429`)**: Free tiers (notably `felo/felo-chat`) enforce a per-window quota. A burst of parallel calls exhausts it, so the next request is refused until the window resets.
|
||||
2. **Broken model in passthrough (`400`/`401`)**: `auto/*` pools can include passthrough models from `opencode` that are registered in the catalog but have no live credentials (e.g. `oc/north-mini-code-free` → `401`). The auto-router tries one, fails, and the error propagates before fallback kicks in.
|
||||
3. **Concurrency amplification (`429` under load)**: When multiple agent/cron sessions hit `auto` at once, the aggregate request rate exceeds what free providers tolerate, so legitimate calls get flagged as abusive.
|
||||
|
||||
**Verified fix (community-reported, 2026-08-10)**: tune three environment variables so that rotation, concurrency, and fallback absorb the free-tier churn instead of dying on it:
|
||||
|
||||
```bash
|
||||
export OMNIROUTE_ROTATE_ON_400=true # hop to another model/provider on 400/401 (skips broken passthrough models)
|
||||
export OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT=4 # raise the heavyweight admission ceiling (default 1) so long-context bursts are not rejected
|
||||
export OMNIROUTE_CHAT_ADMISSION_QUEUE_MS=5000 # longer bounded wait for heavyweight capacity instead of an immediate retryable 503
|
||||
```
|
||||
|
||||
Set these in the OmniRoute process environment (the daemon, e.g. via the LaunchAgent plist or `systemctl edit`), then restart OmniRoute. The rotation flag is the single highest-leverage lever: it converts a hard failure into a transparent retry against a healthy provider in the pool.
|
||||
|
||||
**Note**: `OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT` (default `1`, per process) caps how many heavyweight — long-context — requests run at once; the bound is an admission gate, not a provider rate limiter. Raising it only reduces client-visible `503 chat_admission_busy` rejects for heavy requests. The per-provider rate limiting (`open-sse/services/rateLimitManager.ts`) is governed separately by `RATE_LIMIT_MAX_WAIT_MS`, `RATE_LIMIT_MAX_QUEUE_DEPTH`, and `RATE_LIMIT_AUTO_ENABLE` — see `.env.example`.
|
||||
|
||||
**How to verify it worked**: run your agent/cron twice in quick succession and confirm both succeed. Before the fix, the second run typically throws `429`/`401`. After the fix, failures (if any) are retried transparently and the call completes. You can also `curl /monitoring/health` and watch the `rateLimitedUntil` field on the provider connections and the `circuitBreakers.providerBreakers[].state` for the affected providers — the state is one of `CLOSED`, `DEGRADED`, `OPEN`, or `HALF_OPEN` (see `src/shared/utils/circuitBreaker.ts`), and a provider that keeps failing will flip `CLOSED → DEGRADED → OPEN` before the reset window lets a probe through (`HALF_OPEN`).
|
||||
|
||||
**If you still see 429**: the active account for that provider has genuinely exhausted its *quota* (not just rate). Add a second account for the same provider in the OmniRoute dashboard → Providers → Accounts, or mix in another free provider (e.g. `routeway`, `auggie`). Rotation only helps with transient rate/400/401; a hard quota exhaustion requires a second credential or a different provider.
|
||||
|
||||
**If you see 403 on vision models (`auto/vision`, `bazaarlink/*`)**: the connected account lacks a paid plan that includes vision, or the API key has insufficient permissions. Verify in the provider dashboard that the key scope includes vision/multimodal, or connect a paid tier account and keep it as the vision target.
|
||||
|
||||
---
|
||||
|
||||
## npm install Warnings (ERESOLVE / peer / deprecated)
|
||||
|
||||
When you run `npm install -g omniroute`, you may see a wall of warnings like `npm warn ERESOLVE`, peer-dependency notices, and `deprecated` messages. **These are expected and harmless.** Your install succeeded if you see `added <N> packages` in the output.
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
---
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 340 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (109 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
|
||||
|
||||
> OmniRoute is a free, open-source AI Gateway that acts as a universal API proxy for multi-provider LLMs. It provides smart routing, automatic fallback, load balancing, and format translation across 339 AI providers — all through a single OpenAI-compatible endpoint. Includes a built-in MCP Server (105 tools), A2A v0.3 protocol, Memory/Skills systems, Cloud Agents (codex, cursor, devin, jules), Guardrails framework, and an Electron desktop app.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -18,7 +21,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
|
||||
- **Runtime:** Node.js `>=22.0.0 <23 || >=24.0.0 <27`, ES Modules (`"type": "module"`)
|
||||
- **Framework:** Next.js 16 (App Router) with TypeScript 6
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 148 migrations)
|
||||
- **Database:** SQLite via better-sqlite3 (local, zero-config, 145 migrations)
|
||||
- **State management:** Zustand (client), SQLite (server persistence)
|
||||
- **UI:** React 19, Tailwind CSS 4, Recharts for analytics, @lobehub/icons for 130+ provider SVG icons
|
||||
- **Auth:** OAuth 2.0 (PKCE) for providers, bcrypt for local user auth
|
||||
@@ -106,7 +109,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ └── streaming.ts # SSE streaming for A2A
|
||||
│ │ ├── acp/ # Agent Communication Protocol registry and manager
|
||||
│ │ ├── compliance/ # Compliance policy engine
|
||||
│ │ ├── db/ # SQLite database layer (117 modules + migrations)
|
||||
│ │ ├── db/ # SQLite database layer (99 modules + migrations)
|
||||
│ │ │ ├── core.ts # Database initialization, connection, schema
|
||||
│ │ │ ├── providers.ts # Provider connection CRUD
|
||||
│ │ │ ├── models.ts # Model catalog management
|
||||
@@ -128,7 +131,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ │ ├── secrets.ts # Secrets management
|
||||
│ │ │ ├── stateReset.ts # State reset utilities
|
||||
│ │ │ ├── migrationRunner.ts # Schema migration runner
|
||||
│ │ │ └── migrations/ # 148 versioned SQL migration files
|
||||
│ │ │ └── migrations/ # 117 versioned SQL migration files
|
||||
│ │ ├── evals/ # Eval runner and scheduler
|
||||
│ │ ├── memory/ # Persistent conversational memory
|
||||
│ │ │ ├── extraction.ts # Memory extraction from conversations
|
||||
@@ -169,7 +172,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ └── manager.ts # MITM proxy manager
|
||||
│ ├── shared/ # Shared utilities, components, and constants
|
||||
│ │ ├── components/ # Reusable UI components (Card, Badge, Button, Modal, Sidebar, ProviderIcon, etc.)
|
||||
│ │ ├── constants/ # Provider definitions (340), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── constants/ # Provider definitions (339), model lists, pricing, routing strategies, MCP scopes
|
||||
│ │ ├── contracts/ # Shared API contracts
|
||||
│ │ ├── hooks/ # React hooks
|
||||
│ │ ├── middleware/ # Shared middleware utilities
|
||||
@@ -211,11 +214,11 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ │ ├── moderations.ts # Content moderation
|
||||
│ │ ├── rerank.ts # Reranking API
|
||||
│ │ └── search.ts # Web search API
|
||||
│ ├── mcp-server/ # Built-in MCP server (109 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ ├── mcp-server/ # Built-in MCP server (105 tools, 3 transports: stdio/SSE/streamable-HTTP)
|
||||
│ │ ├── server.ts # MCP server core (tool registration, scope enforcement)
|
||||
│ │ ├── tools/ # Tool implementations (advancedTools, memoryTools, skillTools)
|
||||
│ │ ├── schemas/ # Zod input schemas (tools, audit, a2a)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (33 scopes)
|
||||
│ │ ├── scopeEnforcement.ts # Scope-based access control (31 scopes)
|
||||
│ │ ├── audit.ts # Tool call audit logging
|
||||
│ │ ├── runtimeHeartbeat.ts # MCP runtime heartbeat
|
||||
│ │ └── httpTransport.ts # HTTP transport handler
|
||||
@@ -266,7 +269,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
│ ├── i18n/ # 43-language translated docs
|
||||
│ ├── architecture/ # ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, REPOSITORY_MAP.md, AUTHZ_GUIDE.md, RESILIENCE_GUIDE.md, QUALITY_GATES.md
|
||||
│ ├── reference/ # API_REFERENCE.md, PROVIDER_REFERENCE.md, CLI-TOOLS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (109 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── frameworks/ # MCP-SERVER.md (105 tools), A2A-SERVER.md, SKILLS.md, MEMORY.md, CLOUD_AGENT.md, EVALS.md, WEBHOOKS.md
|
||||
│ ├── routing/ # AUTO-COMBO.md (14-factor scoring), REASONING_REPLAY.md
|
||||
│ ├── security/ # GUARDRAILS.md, COMPLIANCE.md, STEALTH_GUIDE.md, PUBLIC_CREDS.md, ERROR_SANITIZATION.md
|
||||
│ ├── guides/ # USER_GUIDE.md, TROUBLESHOOTING.md, ELECTRON_GUIDE.md, I18N.md
|
||||
@@ -281,7 +284,7 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
## Key Features (v3.8.50)
|
||||
|
||||
### Core Proxy
|
||||
- **340 AI providers** with automatic format translation
|
||||
- **339 AI providers** with automatic format translation
|
||||
- **Provider categories**: Free (90+ free tiers), OAuth, API Key, Self-Hosted, Custom (OpenAI/Anthropic-compatible)
|
||||
- **18 routing strategies**: priority, weighted, round-robin, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, context-relay, fusion, pipeline
|
||||
- **4-tier fallback**: Subscription → API Key → Cheap → Free
|
||||
@@ -349,9 +352,9 @@ OmniRoute solves the problem of managing multiple AI provider subscriptions, quo
|
||||
- **A2A** — Agent-to-Agent v0.3 protocol (JSON-RPC 2.0, 6 skills: smart-routing, quota-management, provider-discovery, cost-analysis, health-report, list-capabilities)
|
||||
- **ACP** — Agent Communication Protocol registry and manager
|
||||
|
||||
### MCP Server (109 Tools)
|
||||
### MCP Server (105 Tools)
|
||||
|
||||
109 tools across modules: **44 canonical** (health, combos, quotas, routing, cost, models, cache,
|
||||
105 tools across modules: **43 base** (health, combos, quotas, routing, cost, models, cache,
|
||||
diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool**, **notion**,
|
||||
**obsidian**, **localCorpus**, **gamification**, and **plugin** modules. Full per-tool inventory:
|
||||
`docs/frameworks/MCP-SERVER.md`.
|
||||
@@ -394,7 +397,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
8. **ProviderIcon component:** Unified icon system using `@lobehub/icons` (130+ SVG) with PNG fallback and generic icon fallback chain. Used on providers, dashboard, and agents pages.
|
||||
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 117 `src/lib/db/` modules with 148 SQL migrations.
|
||||
9. **DB architecture:** `localDb.ts` is a re-export layer only — real logic lives in 99 `src/lib/db/` modules with 117 SQL migrations.
|
||||
|
||||
10. **Upstream headers:** Custom headers merged in executors after default auth; same header name replaces executor value. Forbidden header names in `src/shared/constants/upstreamHeaders.ts`.
|
||||
|
||||
@@ -438,7 +441,7 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
4. **Environment variables:** All configuration is in `.env` (from `.env.example`). Key vars: `PORT`, `NEXT_PUBLIC_BASE_URL`, `API_KEY`, `ADMIN_PASSWORD`.
|
||||
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 148 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
5. **Database layer:** Operations go through `src/lib/db/` modules (117 domain-specific files, 145 migrations). `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module.
|
||||
|
||||
6. **Tests** use Node.js built-in test runner + Vitest. Run `npm test`. Vitest for MCP/autoCombo (`npm run test:vitest`). Playwright for E2E (`npm run test:e2e`). Coverage gate: ratchet vs `quality-baseline.json`, absolute floor 60% statements/lines/functions/branches.
|
||||
|
||||
@@ -479,10 +482,10 @@ diagnostics) plus **memory**, **skill**, **agentSkill**, **githubSkill**, **pool
|
||||
|
||||
## v3.8.x Highlights
|
||||
|
||||
- **340-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **339-provider catalog** with 90+ free tiers, one-click account imports, and bulk key add
|
||||
- **19 routing strategies** — including `fusion` (parallel panel + judge synthesis), `pipeline`, `reset-aware`, `reset-window`, `headroom`, and `context-relay`
|
||||
- **14-factor Auto-Combo scoring** with bandit exploration and progressive cooldown
|
||||
- **MCP server expanded to 109 tools / 33 scopes** (canonical + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **MCP server expanded to 105 tools / 31 scopes** (base + memory/skill/agentSkill/githubSkill/pool/notion/obsidian/localCorpus/gamification/plugin modules)
|
||||
- **Cloud Agents** (Codex Cloud, Devin, Jules), **Guardrails**, **Evals**, **Webhooks**, **Compliance** frameworks
|
||||
- **Embedded services** manager (install/start/stop bundled services from the dashboard)
|
||||
- **Prompt compression** (RTK + Caveman codecs) saving up to ~95% tokens on eligible traffic
|
||||
|
||||